File: configure-cmake

package info (click to toggle)
openmolcas 25.02-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 170,204 kB
  • sloc: f90: 498,088; fortran: 139,779; python: 13,587; ansic: 5,745; sh: 745; javascript: 660; pascal: 460; perl: 325; makefile: 17
file content (484 lines) | stat: -rwxr-xr-x 13,967 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
#!/usr/bin/perl
#***********************************************************************
# This file is part of OpenMolcas.                                     *
#                                                                      *
# OpenMolcas is free software; you can redistribute it and/or modify   *
# it under the terms of the GNU Lesser General Public License, v. 2.1. *
# OpenMolcas is distributed in the hope that it will be useful, but it *
# is provided "as is" and without any express or implied warranties.   *
# For more details see the full text of the license in the file        *
# LICENSE or in <http://www.gnu.org/licenses/>.                        *
#                                                                      *
# Copyright (C) 2016, Steven Vancoillie                                *
#***********************************************************************
#
# configure-cmake
#
# Front-end for cmake configuration of Molcas.
# For detailed usage documentation read the help subroutines.
#
# This script is intended to provide an easy-to-use wrapper
# around cmake, accepting options more in the style of the
# original configure script, and providing automated creation
# of aptly named build directories.
#
# Note that this script is NOT intended to be a full wrapper
# or replacement for cmake. Instead, if you want to have full
# flexibility it is strongly recommended to use cmake directly
# rather than adapt this script to scratch every developer's itch!
#
# Steven Vancoillie, beginning of 2016

# perl modules
#use warnings;
use Getopt::Long;
use Cwd;
use File::Basename;
use File::Copy;
use File::Path;
use File::Spec;
use POSIX qw(strftime);

# use proper locale
use POSIX qw(locale_h);
setlocale(LC_ALL, "C");

# set hot pipes, flushes output
$| = 1;

# my name
my $me = basename($0);

# trap interrupt
$SIG{INT} = sub { error("\nSTOP: user has terminated $me!\n") };

# store environment info
my $MACHINE=`uname -a`;
chomp ($MACHINE);
my @DATE = localtime;
my $DATE = strftime("%c",@DATE);

my $starting_cwd = cwd;

my @SAVED_OPTIONS = @ARGV;

# default options
my %opt = ();
GetOptions ( \%opt,
             "h",
             "help",
             "quiet",
             "default",
             # basic configuration/build info
             "clean",
             "verbose",
             "j=i",
             "name=s",
             # compilers
             "compiler=s",
             # build types
             "opt=s",
             # parallel
             "mpi!",
             "omp!",
             # linear algebra library locations
             "mkl=s",
             "aocl=s",
             "openblas=s",
             "cublas=s",
             "nvblas=s",
             # extra stuff
             "gperftools!",
             "gcov!",
             "hdf5!",
             "tools!",
             "msym!",
             "dmrg!",
             "dmrg_debug!",
             "hdf5_f2003!",
             # advanced
             "prefix=s",
             "bounds!",
             "ga=s",
           ) or help(1);

# do we need help?
help(0) if ($opt{h} or $opt{help} or (scalar keys %opt < 1));

my $molcasroot = cwd;
my $molcashome = File::Spec->catfile ($molcasroot, '.molcashome');
if (! -f $molcashome) {
    die "you need to run this script from a Molcas root directory!"
}

# prepare source if necessary
my $git = which('git');
if ($git and -d '.git') {
    if ($opt{msym} or $opt{dmrg}) {
        msg_nl("$me: updating submodules...");
        if ($opt{msym}) {
            system('git', 'submodule', 'update', '--init', 'External/libmsym');
        }
        if ($opt{dmrg}) {
            system('git', 'submodule', 'update', '--init', 'External/gen1int-molcaslib');
            system('git', 'submodule', 'update', '--init', 'External/hdf5_f2003_interface');
            system('git', 'submodule', 'update', '--init', 'External/qcmaquis_driver');
            system('git', 'submodule', 'update', '--init', 'External/qcmaquis_sutie');
        }
    }
}

my $builddir = File::Spec->rel2abs('builds');
unless (-d $builddir) {
    mkdir $builddir or die "could not create build directory";
}

# defaults

$opt{clean} = 1
    unless defined $opt{clean};

$opt{compiler} = 'gnu'
    unless defined $opt{compiler};

$opt{opt} = 'dev'
    unless defined $opt{opt};

$opt{j} = 1
    unless defined $opt{j};

unless (defined $opt{name}) {
    my @name = ($opt{compiler}, $opt{opt});
    push(@name, 'mpi') if $opt{mpi};
    push(@name, 'omp') if $opt{omp};
    push(@name, 'ga') if defined $opt{ga};
    push(@name, 'mkl') if defined $opt{mkl};
    push(@name, 'aocl') if defined $opt{aocl};
    push(@name, 'openblas') if defined $opt{openblas};
    push(@name, 'bounds') if defined $opt{bounds};
    $opt{name} = join('_', @name);
}
my $build = File::Spec->catdir($builddir, $opt{name});
my $maker = 'make-' . $opt{name};
my $runner = 'molcas-' . $opt{name};

# build up the cmake options

my @cmake_options;

if ($opt{prefix}) {
    push @cmake_options, "-DCMAKE_INSTALL_PREFIX=$opt{prefix}";
}

# compiler

if ($opt{compiler} eq 'gnu') {
    $fc = which("gfortran");
    $cc = which("gcc");
    $cxx = which("g++");
} elsif ($opt{compiler} eq 'intel') {
    $fc = which("ifort");
    $cc = which("icc");
    $cxx = which("icc");
} elsif ($opt{compiler} eq 'pgi') {
    $fc = which("pgfortran");
    $cc = which("pgcc");
    $cxx = which("pgCC");
} elsif ($opt{compiler} eq 'sun') {
    $fc = which("sunf90");
    $cc = which("suncc");
    $cxx = which("sunCC");
} else {
    error("unknown compiler ID: $opt{compiler}");
}

checkexe($fc);
checkexe($cc);
checkexe($cxx);

push @cmake_options, "-DCMAKE_Fortran_COMPILER=$fc";
push @cmake_options, "-DCMAKE_C_COMPILER=$cc";
push @cmake_options, "-DCMAKE_CXX_COMPILER=$cxx" if $opt{dmrg};

# build type

if ($opt{opt} eq 'normal') {
    push @cmake_options, '-DCMAKE_BUILD_TYPE=Release';
} elsif ($opt{opt} eq 'dev') {
    push @cmake_options, '-DCMAKE_BUILD_TYPE=RelWithDebInfo';
} elsif ($opt{opt} eq 'debug') {
    push @cmake_options, '-DCMAKE_BUILD_TYPE=Debug';
} elsif ($opt{opt} eq 'garble') {
    push @cmake_options, '-DCMAKE_BUILD_TYPE=Garble';
} elsif ($opt{opt} eq 'fast') {
    push @cmake_options, '-DCMAKE_BUILD_TYPE=Fast';
} else {
    error("unknown optimization level: $opt{opt}");
}

# boundary checks

cmake_toggle($opt{bounds}, 'BOUNDS', \@cmake_options);

# parallel

if ($opt{ga}) {
    $ENV{GAROOT} = $opt{ga};
    push @cmake_options, '-DGA=ON';
    $opt{mpi} = 1;
}
cmake_toggle($opt{mpi}, 'MPI', \@cmake_options);

cmake_toggle($opt{omp}, 'OPENMP', \@cmake_options);

# linear algebra

if ($opt{mkl}) {
    checkdir('mkl');
    $ENV{MKLROOT} = $opt{mkl};
    push @cmake_options, '-DLINALG=MKL';
} elsif ($opt{aocl}) {
    checkdir('aocl');
    $ENV{AOCLROOT} = $opt{aocl};
    push @cmake_options, '-DLINALG=AOCL';
} elsif ($opt{openblas}) {
    checkdir('openblas');
    $ENV{OPENBLASROOT} = $opt{openblas};
    push @cmake_options, '-DLINALG=OpenBLAS';
}

if ($opt{nvblas}) {
    checkdir('nvblas');
    $ENV{CUDAROOT} = $opt{nvblas};
    push @cmake_options, '-DNVBLAS=ON';
} elsif ($opt{cublas}) {
    checkdir('cublas');
    $ENV{CUDAROOT} = $opt{cublas};
    push @cmake_options, '-DCUBLAS=ON';
}

# extra options

cmake_toggle($opt{gperftools}, 'GPERFTOOLS', \@cmake_options);
cmake_toggle($opt{gcov}, 'GCOV', \@cmake_options);
cmake_toggle($opt{hdf5}, 'HDF5', \@cmake_options);
cmake_toggle($opt{tools}, 'TOOLS', \@cmake_options);
cmake_toggle($opt{msym}, 'MSYM', \@cmake_options);
cmake_toggle($opt{dmrg}, 'DMRG', \@cmake_options);
cmake_toggle($opt{dmrg_debug}, 'DMRG_DEBUG', \@cmake_options);
cmake_toggle($opt{hdf5_2003}, 'HDF5_2003', \@cmake_options);

# prepare the configure and build command

my @cmake_command = ('cmake');
push @cmake_command, @cmake_options;
push @cmake_command, $molcasroot;

my @make_command = ('make', "-j$opt{j}");
push @make_command, "VERBOSE=1" if $opt{verbose};

# construct the build script

open(MAKER, '>', $maker) or die "could not open file";
print MAKER <<"EOF";
#!/bin/sh
# $0 @SAVED_OPTIONS
mkdir -p builds/$opt{name}
cd builds/$opt{name} || exit 1
# @cmake_command
echo running make inside the build directory...
@make_command \$*
EOF
close(MAKER);
chmod 0755, $maker;

open(RUNNER, '>', $runner) or die "could not open file";
print RUNNER <<"EOF";
#!/bin/sh
export MOLCAS=$build
molcas \$*
EOF
close(RUNNER);
chmod 0755, $runner;

# run initial cmake configuration

chdir $builddir or die "could not cd into $builddir";

if ($opt{clean}) {
    File::Path->remove_tree($opt{name});
}

if (! -d $opt{name}) {
    mkdir $opt{name} or die "Failed to create build directory!";
}

chdir $opt{name} or die "could not cd into $opt{name}";
msg_nl("$me: running @cmake_command");
system(@cmake_command) == 0
    or die "system call failed: rc = $?";
msg("\n");
msg("$me: Configuration finished!\n");
msg(">>>> To compile Molcas, run: ./$maker\n");
msg(">>>> To use Molcas, run: ./$runner\n");
msg("\n");
exit 0;

########################################################################
# subroutines
########################################################################

#----------------------------------------------------------
# extended help information with explanation of all options
#----------------------------------------------------------

sub help {
        print "$0 [options]\n";
        print <<"EOF";

options:

    -h|--help           print the help (you're reading it)

    --quiet             do not print any output

    --default           configure with default options

    --[no-]clean        toggle removal of the build directory before configuring
                        (default: clean)

    --name X            choose name X for the build
                        By default, a suitable name is constructed from the list
                        of supplied options. This allows you to overwrite that name.
                        The name is used for the build directory, the make script,
                        and the custom molcas command wrapper.

    -j N                use N processes during compilation (speeds up compilation)

    --verbose           print complete compilation commands during the build step

    --compiler {gnu|intel|pgi|sun}
                        choose compiler suite

        gnu             use GCC (gfortran/gcc/g++) compilers (default)
        intel           use Intel (ifort/icc) compilers
        pgi             use PGI (pgfortran/pgcc/pgCC) compilers
        sun             use Solaris Studio (sunf90/suncc/sunCC) compilers

    --opt {normal|dev|garble|debug|fast}
                        choose optimization level

        normal          normal optimization, no debug symbols
        dev             normal optimization with debug symbols
        garble          normal optimization with debug symbols, and
                        initialize with garbage and use fpe trapping
        debug           no optimization with debug symbols
        fast            aggressive optimization, no debug symbols
                        WARNING: this option is known to cause problems,
                        so use this at your own risk! (**unsupported**)

    --[no-]mpi          toggle MPI parallellization
    --[no-]omp          toggle OpenMP multithreading
                        This option links to the multithreaded versions of the
                        BLAS/LAPACK libraries if available.

  external BLAS/LAPACK options: as PATH you to provide the root directory
                                of the chosen BLAS/LAPACK libraries

    --mkl PATH          link to Intel MKL located in PATH
    --aocl PATH         link to AOCL located in PATH
    --openblas PATH     link to OpenBLAS located in PATH

  advanced:

    --prefix PATH       location of the installation (default: /opt/molcas/)
                        (only relevant if you plan to use 'make install')

    --ga GAROOT         enable Global Arrays parallellization (activates MPI
                        automatically) and specify the root location of the
                        GA library in GAROOT

  debugging aids:

    --[no-]bounds       enable/disable bounds checking (only with GCC >= 4.8)

Any options can be used also in a short form, as long
as it can be uniquely identified, e.g. -h instead of
--help or -q instead of --quiet, etc.

Examples:

Configure with default options:

  $0 --default

Configure a production version (serial), with Intel compilers and multithreaded MKL:

  $0 --compiler intel --opt normal --mkl /path/to/MKL --omp

Configure a developing version with bounds checking and garbage initialization,
compile it with 4 processes and verbose output, call it "test":

  $0 --compiler gnu --opt garble --bounds --verbose -j 4 --name test

EOF
        exit shift(@_);
}

# output control
#---------------

sub msg {
        print @_ unless ($opt{quiet});
}

sub msg_nl {
        unless ($opt{quiet}) {
                while (my $line = shift) {
                        print "$line\n";
                }
        }
}

sub error {
        print STDERR "Error: @_" unless ($opt{quiet});
        exit 1;
}

sub cmake_toggle {
    my $value = shift;
    my $name = shift;
    my $list = shift;
    if (defined $value) {
        if ($value) {
            push @$list, "-D$name=ON";
        } else {
            push @$list, "-D$name=OFF";
        }
    }
}

sub checkdir {
    my $name = shift;
    unless (-d $opt{$name}) {
        error("you supplied the option --$name with a directory that does not exist: $opt{$name}\n");
    }
}

sub checkexe {
    my $name = shift;
    unless (-e $name) {
        error("the executable you supplied cannot be found: $name\n");
    }
    unless (-x $name) {
        error("the file you supplied is not executable: $name\n");
    }
}

sub which {
    my $exename = shift;
    my $exepath = `which $exename`
        or die "which failed, check if $exename is installed!";
    chomp $exepath;
    return $exepath;
}