Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Compiling large Fortran projects

5 views
Skip to first unread message

dirkj...@my-deja.com

unread,
Jun 10, 1999, 3:00:00 AM6/10/99
to
I am trying to find an easy way to compile a large (say >50 files)
Fortran program. It is written in F90 and consists of a main file and a
lot of module files (each module in a separate file). When I compile
the main file the compiler of course complains about other (object)
files not existing so I compile them etc. This can take a lot of time
especially when you have to figure out the correct order of
compilation. The workaround I use is to put a lot of 'include'
statements in a separate file (in the correct order) and then compile
it. This has the additional advantage that inter-modular optimizations
can be performed (such as inlining, etc.). The downside is that for
each file I add to the project I have to find out where it should be in
the 'include' list.

What I need is a small program that scans the main file (not the one
containing the 'include's) for 'use' statements, does the same for the
files that are being 'used', etc. (recursively). This would enable the
possibility to track which module is lowest in the tree (and can thus
be compiled first). If such a util would then write a small .f90 file
with a bunch of includes in the correct order the whole thing should
compile properly and fully optimized. Does anyone know of the existence
of such a utility?

Thanks,

Dirk-Jan


Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.

David Shain

unread,
Jun 10, 1999, 3:00:00 AM6/10/99
to

dirkj...@my-deja.com wrote:

You are describing the "make" program. Some form of this program is
available on every system I have ever seen. This is one of the most basic
programming utilities around. There are books available on just using make
(O'Reilly). If you have 50 files, you need to start using this...good luck,

david


Gene Wagenbreth

unread,
Jun 11, 1999, 3:00:00 AM6/11/99
to
I thought that he wanted a program to look at the use of modules
in his program and figure out the dependencies for MAKE. If I
change a module, all modules that use it need to be recompiled,
and all program units that use it must be recompiled, and all that
use any of the recompiled modules, etc.
--
-------------------------------------------------------------------
Gene Wagenbreth Programming for Dollars
My opinions are mine, I think.
-------------------------------------------------------------------

dirkj...@my-deja.com

unread,
Jun 11, 1999, 3:00:00 AM6/11/99
to
In article <37602AE6...@nr.infi.net>,
dsh...@nr.infi.net wrote:

> You are describing the "make" program. Some form of this program is
> available on every system I have ever seen. This is one of the most
basic
> programming utilities around. There are books available on just using
make
> (O'Reilly). If you have 50 files, you need to start using this...good
luck,
>
> david
>

Yes, I know of this utility. It still requires the user to state where
the files are located and in which order they must be processed. This
can take some time to figure out, especially when files are
added/deleted from the project constantly.

Jurgen Singer

unread,
Jun 11, 1999, 3:00:00 AM6/11/99
to
He is indeed describing the make program. However, as
he also states, one still has to create the dependency
lists by hand. Most C/C++ compilers offer a flag that
creates the appropriate make dependencies, which then
can be included into the makefile. With the introduction
of modules into Fortran 90, these dependencies can be a
big pain, especially for larger projects. It is about
time that Fortran compiler vendors offer the same
convenience as most C/C++ compiler vendors.

In addition, the generation of module and object files
from the same source file forces a lot of unnecessary
recompilations. If only the implementation, but not the
interface of a source file changes, then an existing
module file should not be overwritten. Otherwise, all
source files depending on this module will also be
recompiled. This has a tendency to cascade through a
large portion of a project. I solve this problem partially
by including my module files from a directory separate
from the one where I create them. New module files are
moved to the include directory only if they differ from
the old one. This technique is somewhat clumsy and not
reliable, for example, it won't work if a compiler vendor
decides to include a time stamp in the moddule file. Hence,
this is also an issue compiler vendors should address.

-- Jurgen

Mike Prager

unread,
Jun 11, 1999, 3:00:00 AM6/11/99
to
"Automake" by Polyhedron is supposed to figure out the dependencies
automatically. Unfortunately, the documationtation is very thin. In
my case, I went back to using a regular make utility (lots of hand
work, but lots of documentation). However, Lahey supplies "automake"
with their compiler, so there may be other users of it who could be
persuaded to say something about it.


Mike Prager
Beaufort, NC

John Appleyard

unread,
Jun 11, 1999, 3:00:00 AM6/11/99
to
In article <7jojgd$jps$1...@nnrp1.deja.com>, dirkj...@my-deja.com writes

>I am trying to find an easy way to compile a large (say >50 files)
>Fortran program. It is written in F90 and consists of a main file and a
>lot of module files (each module in a separate file). When I compile
>the main file the compiler of course complains about other (object)
>files not existing so I compile them etc. This can take a lot of time
>especially when you have to figure out the correct order of
>compilation. The workaround I use is to put a lot of 'include'
>statements in a separate file (in the correct order) and then compile
>it. This has the additional advantage that inter-modular optimizations
>can be performed (such as inlining, etc.). The downside is that for
>each file I add to the project I have to find out where it should be in
>the 'include' list.
>
>What I need is a small program that scans the main file (not the one
>containing the 'include's) for 'use' statements, does the same for the
>files that are being 'used', etc. (recursively). This would enable the
>possibility to track which module is lowest in the tree (and can thus
>be compiled first). If such a util would then write a small .f90 file
>with a bunch of includes in the correct order the whole thing should
>compile properly and fully optimized. Does anyone know of the existence
>of such a utility?

Our AUTOMAKE utility does that. Well almost. What you describe is
difficult, as a USE statement doesn't specify where the module can be
found, and there is no necessary relationship between the module name
and a file name. Instead, it takes the set of files which are
candidates for re-compilation as one or more wild-cards

e.g.

FILES=*.f90
AND
FILES=..\mylib\*.f

and does all the dependency analysis to ensure everything is compiled in
the right order. AUTOMAKE automatically updates the dependency data as
you work on your source code - for example, if you add a new USE,
AUTOMAKE knows about the extra dependencies without a complete rebuild.

AUTOMAKE is part of our plusFORT suite, but is available separately -
contact sa...@polyhedron.com if you're interested.

Incidentally, our AUTOMAKE should not be confused with the GNU automake
which is part of Linux. The clash of names is unfortunate, as there is
some similarity in functionality (though as I understand it, GNU
automake does not understand F90). So far as I can see at present, the
first release of our AUTOMAKE (on Linux as well as other platforms)
predates the GNU version by around a year...
--
John Appleyard Jo...@polyhedron.com Jo...@polyhedron.co.uk

Polyhedron Software Ltd.
Programs for Programmers - QA, Compilers, Graphics

************ Visit our Web site on http://www.polyhedron.co.uk/ ************

bg...@my-dejanews.com

unread,
Jun 11, 1999, 3:00:00 AM6/11/99
to
dirkj...@my-deja.com writes:

> I am trying to find an easy way to compile a large (say >50 files)
> Fortran program. It is written in F90 and consists of a main file and a
> lot of module files (each module in a separate file). When I compile
> the main file the compiler of course complains about other (object)
> files not existing so I compile them etc. This can take a lot of time
> especially when you have to figure out the correct order of
> compilation. The workaround I use is to put a lot of 'include'
> statements in a separate file (in the correct order) and then compile
> it. This has the additional advantage that inter-modular optimizations
> can be performed (such as inlining, etc.). The downside is that for
> each file I add to the project I have to find out where it should be in
> the 'include' list.

There is another downside: you are recompiling all modules whenever
one of them changes. Where you really need cross-module optimisations,
that's hard to avoid; but most of the time you'll want something
smarter, that only recompiles the files that depend on the changes.

If you have access to the UNIX tools "make" and "perl" on your
platform, you could use Kate Hedstrøm's "sfmakedepend". There
are a couple of versions floating around on the net. Note that
although make and perl were originally developed for Unix, they
have since been ported to some other environments.

Some vendors may also provide smart compilation environments, in which
you give the system a list of all source files comprising a program
and it figures out the right compilation order by itself. Always check
the documentation for your system.

> What I need is a small program that scans the main file (not the one
> containing the 'include's) for 'use' statements, does the same for the
> files that are being 'used', etc. (recursively). This would enable the
> possibility to track which module is lowest in the tree (and can thus
> be compiled first). If such a util would then write a small .f90 file
> with a bunch of includes in the correct order the whole thing should
> compile properly and fully optimized. Does anyone know of the existence
> of such a utility?

sfmakedepend will do it. (Except it will append a list of dependencies
to a makefile rather than write a .f90 file full of INCLUDE lines;
but that's easy to change if really desired. It may be even easier to
make sfmakedepend issue the compilation commands in the right order.)

bg...@my-dejanews.com

unread,
Jun 11, 1999, 3:00:00 AM6/11/99
to
Jurgen Singer <jks...@NOyahooSPAM.com> writes:

> He is indeed describing the make program. However, as
> he also states, one still has to create the dependency

> lists by hand. [snip]

All right. Since no one seems to remember Kate Hedstrøm's
sfmakedepend, here is the version I use at the moment (it
contains some improvements upon the original). Feel free
to add support for more compilers.

My makefiles normally include something along the lines of:

depend Makefile.depend : $(SRCS) $(INCS)
-touch Makefile.depend
$(SFMAKEDEPEND) -f Makefile.depend $(SRCS)
include Makefile.depend

and (this varies from platform to platform):

SFMAKEDEPEND = sfmakedepend --compiler=nag --nolib-deps --depend=obj

----------------------------------------------------------------------------
#!/usr/bin/perl
#
# $Id: sfmakedepend,v 1.2 1998/08/06 00:12:28 Exp $
#
# Usage: sfmakedepend [-s] [-e ext] [-f file] [-I incdir]
# [-m mod_ext] [-c] [-p] [-g] [-h] [-o obj_ext]
# [--case=up|down|asis]
# [--compiler=cray|sgiold|sgi|nag|xlf|parasoft|
# vast|pgi|hp|sun|absoft]
# [--depend=mod|obj] [--no-lib-deps]
# [-a add_ext] file ...
#
# This is a makedepend script for Fortran, including Fortran 90.
# It searches for Fortran style includes, C preprocessor includes,
# and module dependencies to the extent that I understand them.
# ["I" means the original author, Kate Hedstrom. SG]
#
# Your files must have an extension listed in the @suffixes list
# below. You might also want to modify $compile_string if you use
# the -c or -p option. I call the compiler $(CFT) for historical
# reasons. [Changed to $(F90). SG]
#
# The switch [-s] is for stupid Fortran compilers that don't know
# how to automatically send things through the C preprocessor.
# It is possible to force 'make' to invoke 'cpp' to create a .f
# file from a .F file (which has cpp directives), but make won't
# know that a .f file will depend on the files that the .F file
# included. This option will provide those dependencies.
#
# The [-e ext] switch is used with the [-s] switch for compilers
# which expect an extension other than .f on source files. For
# instance, for the Connection Machine one would use "-e fcm".
#
# The [-f file] switch is used to change the name of the current
# Makefile.
#
# The [-I incdir] option tells sfmakedepend to look in alternate
# directories for the include files. There can be several "-I dir"
# options used at once. The current directory is still searched
# first.
#
# The [-m mod_ext] option tells sfmakedepend what extension to
# use for Fortran 90 module files. The default for "use My_Mod"
# is to list the dependency as "my_mod.mod" since this is what
# NAG f90 and IBM xlf both use. Let me know if other compilers
# use a different filename for the module information.
#
# The [-c] option specifies that the Cray compiler is being used.
# This compiler requires a "-p file.o" option for each object file
# that contains a module used by your current source file.
# [Obsolete. Use --compiler=cray instead. SG]
#
# The [-p] option specifies that the Parasoft compiler is being used.
# This compiler requires a "-module file.o" option for each object file
# that contains a module used by your current source file.
# [Obsolete. Use --compiler=parasoft instead. SG]
#
# The [-g] option specifies that the SGI compiler is being used.
# This compiler names the module file in uppercase with the extension
# .kmo.
# [Doubly obsolete. Use --compiler=sgiold, or upgrade to a newer SGI
# compiler and use --compiler=sgi. SG]
#
# The [-h] option specifies that the HP compiler is being used.
# This compiler names the module file in uppercase with the extension
# .mod (added by Patrick Jessee who also fixed an include bug).
# [Obsoleted by --compiler=hp. SG]
#
# The --case option controls upcasing/downcasing of module names when
# generating module file names. Only relevant where the module file
# name is named after the module rather than after the source file.
#
# The --compiler option controls the type of target compiler.
#
# The --depend option controls whether to use the module information file
# or the module object file in dependencies.
#
# The --no-lib-deps option avoids generating dependencies on modules for
# which source code is not available. A warning is still issued.
#
# The [-o obj_ext] option tells sfmakedepend what extension to use for
# object files. The default is "o", but "obj", for instance, is
# appropriate on MS-DOG etc. This option was added by Dave Love.
#
# The [-a add_ext] option (also added by Dave Love) tells sfmakedepend
# to add targets with extension add_ext to the rules for object files.
# For instance, to operate with (f77) ftnchek .prj files, you could use
# `-a prj' to get rules like:
# foo.prj foo.o: ...
#
# The final arguments contain the list of source files to be
# searched for dependencies.
#
# EXAMPLE
# sfmakedepend -I /usr/local/include *.F
#
# NOTES
# This makedepend script is my first attempt at using perl 5
# objects. Therefore, it may not be the best example of how
# to do this. Also, it requires perl 5 and will die if you
# to use it with an older perl. The latest version is
# available from:
#
# http://marine.rutgers.edu/po/perl.html
# ftp://ahab.rutgers.edu/pub/perl/sfmakedepend
#
# Fortran 90 introduces some interesting dependencies. Two
# compilers I have access to (NAG f90 and IBM xlf) produce a
# private "mod_name.mod" file if you define "module mod_name"
# in your code. This file is used by the compiler when you
# use the module as a consistency check (type-safe). On the
# other hand, the Cray and Parasoft compilers store the module
# information in the object file and then files which use the
# modules need to be compiled with extra flags pointing to the
# module object files.
#
# This script assumes that all the files using and defining
# modules are in the same directory and are all in the list of
# files to be searched. It seems that the industry has not
# settled on a practical way to deal with a separate modules
# directory, anyway.
#
# I sometimes include non-existent files as a compile time
# consistency check:
#
# #ifndef PLOTS
# #include "must_define_PLOTS" /* bogus include */
# #endif
#
# This program warns about include files it can't find, but
# not if there is a "bogus" on the same line.
#
# * The f90 module dependencies can confuse some versions of
# make, especially of the System V variety. We use gnu
# make because it has no problems with these dependencies.
#
# BUGS
# It can sometimes produce duplicate dependencies.
#
# It treats C preprocessor includes the same as Fortran
# includes. This can add unnecessary dependencies if you
# use the -s flag and both kinds of includes.
#
# Please let me know if you find any others.
# Kate Hedstrom
# ka...@ahab.rutgers.edu
#

package source_file;

# hashes containing names of included files, modules in files
%inc_files = ();
%main::mod_files = ();

# Constructor
sub new {
my $type = shift;
my $filename = shift;
my $path = shift;
my $self = {};
$self->{'source_file'} = $filename;
$self->{'filepath'} = $path;
$self->{'includes'} = {};
$self->{'uses'} = {};
$self->{'modules'} = {};
bless $self;
}

sub find_includes {
my $self = shift;
my $file = $self->{'filepath'};
my($after, $filepath, $ref, $included, $use, $modname);
local(*FILE);
local($_);

if (-f $file) {
open(FILE, $file) || warn "Can't open $file: $!\n";
} elsif (-f "RCS/$file,v" || -f "$file,v" ) {
system("co $file");
open(FILE, $file) || warn "Can't open $file: $!\n";
$main::rcs{$file} = 1;
} else {
return;
}
while (<FILE>) {
$included = "";
$use = "";
# look for Fortran style includes
if (/^\s*include\s*['"]([^"']*)["']/i) {
$included = $1;
$after = $';
# C preprocessor style includes
} elsif (/^#\s*include\s*["<]([^">]*)[">]/) {
$included = $1;
$after = $';
# Fortran 90 "use"
} elsif (/^\s*use\s+(\w+)/i) {
$use = $1;
# Make the module name lowercase except for SGI & HP.
# May be compiler dependent!!
if ($main::case eq "upper") {
$use = uc($use);
} elsif ($main::case eq "lower") {
$use = lc($use);
}
$self->{'uses'}{$use} = 1;
# Fortran 90 module
} elsif (/^\s*module\s+(\w+)/i) {
$modname = $1;
if ($main::case eq "upper") {
$modname = uc($modname);
} elsif ($main::case eq "lower") {
$modname = lc($modname);
}
# FIXME: really need better parsing here...
unless (lc($modname) eq "procedure") {
$main::mod_files{$modname} = $file;
$self->{'modules'}{$modname} = 1;
}
}
if ($included) {
if ( $inc_files{$included} ) {
$filepath = $inc_files{$included}{'filepath'};
} else {
$filepath = &main::findfile($included);
$ref = new source_file($included, $filepath);
$inc_files{$included} = $ref;
# Search included file for includes
$ref->find_includes();
}
if ( $filepath ) {
$self->{'includes'}{$included} = 1;
} else {
if ($after !~ /bogus/i) {
warn "Can't find file: $included\n";
}
}
}
}
close FILE;
}

sub print_includes {
my $self = shift;
my $target = shift;
my $len_sum = shift;
my($file, $ref);

foreach $file (keys %{$self->{'includes'}}) {
$ref = $inc_files{$file};
my $len = length($ref->{'filepath'}) + 1;
if (($len_sum + $len > 80) &&
(length($target) + 1 < $len_sum)) {
print "\n$target:";
$len_sum = length($target) + 1;
}
print " " . $ref->{'filepath'};
$len_sum += $len;
$len_sum = $ref->print_includes($target, $len_sum);
}
$len_sum;
}

# return list of modules used by included files
sub inc_mods {
my $self = shift;
my($file, $ref, $mod, @sub_list);
my @list = ();

foreach $mod (keys %{$self->{'uses'}}) {
push(@list, $mod);
}

foreach $file (keys %{$self->{'includes'}}) {
$ref = $inc_files{$file};
@sub_list = $ref->inc_mods();
@list = (@list, @sub_list);
}
@list;
}

# filenames containing the list of modules used by file and all its includes
sub find_mods {
my $self = shift;
my($ref, $modname, $file, @list, $base);
my @module_files = ();
my @mod_list = ();
my @tmp_list = ();

# find modules used by include files
if (%{$self->{'includes'}}) {
foreach $file (keys %{$self->{'includes'}}) {
$ref = $inc_files{$file};
@list = $ref->inc_mods();
@tmp_list = @mod_list;
@mod_list = (@tmp_list, @list);
}
}

# add them to the uses list (hash ensures uniqueness)
foreach $modname (@mod_list) {
$self->{'uses'}{$modname} = 1;
}

# now find the filename that contains the module information
foreach $modname (keys %{$self->{'uses'}}) {
if ($main::depend eq "obj") {
if ($file = $main::mod_files{$modname}) {
$base = &main::basename($file, @main::suffixes);
$file = $base . "." . $main::obj_ext;
push(@module_files, $file);
} else {
warn "Don't know where module $modname lives.\n";
}
} else {
if ($main::lib_deps or defined($main::mod_files{$modname})) {
$modname .= "." . $main::mod_ext;
push(@module_files, $modname);
} else {
warn "Couldn't locate source for module $modname\n";
}
}
}
sort(@module_files);
}

sub print {
my $self = shift;
my $source = $self->{'source_file'};
my $compile_string = "\t" . '$(F90) $(F90FLAGS) -c';
my($base, $object, $modname, $flag, $target, $ftarget);

$base = &main::basename($source, @main::suffixes);
$target = $base . "." . $main::obj_ext;
if ($main::stupid) {
$ftarget = $base . "." . $main::ext;
}

$flag = $main::obj_dep_flag;

# print out "include" dependencies
if (%{$self->{'includes'}}) {
my $len_sum = length($target) + 1;
if ($main::add_ext) {
print "$base.$main::add_ext ";
$len_sum += length($base) + length($main::add_ext) + 2;
}
print "$target:";
$self->print_includes($target, $len_sum);
print "\n";
if ($main::stupid) {
$len_sum = length($ftarget) + 1;
print "$ftarget:";
$self->print_includes($ftarget, $len_sum);
print "\n";
}
}

# clean out "use" of modules in own file
foreach $mod ( keys %{$self->{'uses'}} ) {
if ( ${$self->{'modules'}}{$mod} ) {
delete ${$self->{'uses'}}{$mod};
}
}

# print out "use" dependencies
if (%{$self->{'uses'}} || %{$self->{'includes'}}) {
@module_files = $self->find_mods();
my $len_sum = length($target) + 1;
print "$target:";
foreach $file (@module_files) {
my $len = length($file) + 1;
if (($len_sum + $len > 80) &&
(length($target) + 1 < $len_sum)) {
print "\n$target:";
$len_sum = length($target) + 1;
}
$len_sum += $len;
print " " . $file;
}
if ($main::need_f) {
my $len = length($ftarget) + 1;
if (($len_sum + $len > 80) &&
(length($target) + 1 < $len_sum)) {
print "\n$target:";
$len_sum = length($target) + 1;
}
print " " . $ftarget;
}
print "\n";
# extra Cray / Parasoft stuff
if ($flag ne "") {
print $compile_string;
foreach $file (@module_files) {
print $flag . $file;
}
if ($main::stupid) {
print " " . $ftarget . "\n";
} else {
print " " . $source . "\n";
}
}
}
}

# Start of main program
package main;

if ($] < 5.000) { die "Need perl 5.000 or newer\n"; }
use File::Basename;
use Getopt::Long;
@suffixes = qw( .c .C .cc .cxx .cpp .f .F .fcm .FCM .f90 .F90 .for);

GetOptions("s", "e=s", "f=s", "I=s@", "m=s", "c", "p", "g", "h", "o=s", "a=s",
"case=s", "compiler=s", "depend=s", "lib-deps!")
|| die "problem in GetOptions";

# list of directories to search, starting with current directory
@incdirs = @opt_i;

if ($opt_f) {
$mf = $opt_f;
} elsif (-f "makefile") {
$mf = 'makefile';
} else {
$mf = 'Makefile';
}

if ($opt_c) {
$compiler = "cray";
}

if ($opt_p) {
$compiler = "parasoft";
}

if ($opt_g) {
$compiler = "sgiold";
}

if ($opt_h) {
$compiler = "hp";
}

$compiler = $opt_compiler if ($opt_compiler ne "");

$mod_ext = "mod";
$depend = "mod";
if ($compiler eq "cray") {
$cray = 1;
$case = "lower";
$depend = "obj";
$obj_dep_flag = "-p";
} elsif ($compiler eq "parasoft") {
$parasoft = 1;
$case = "lower";
$depend = "obj";
$obj_dep_flag = "-module";
} elsif ($compiler eq "sgiold") {
$mod_ext = "kmo";
$case = "upper";
} elsif ($compiler eq "sgi" or $compiler eq "hp") {
$case = "upper";
} elsif ($compiler eq "vast") {
$mod_ext = "vo";
$case = "lower";
} elsif ($compiler eq "nag" or $compiler eq "xlf" or
$compiler eq "pgi") {
$case = "lower";
} else {
warn "Unknown compiler: $compiler\n";
}

$depend = $opt_depend if defined($opt_depend);
$case = $opt_case if defined($opt_case);

$lib_deps = 1;
$lib_deps = $opt_lib_deps if defined($opt_lib_deps);

# extension used for compiler's private module information
if ($opt_m) {
$mod_ext = $opt_m;
}

# For compilers that don't invoke cpp for you
if ($opt_s) {
$stupid = 1;
}
if ($opt_e) {
$ext = $opt_e;
} else {
$ext = "f";
}

# need to add some more dependencies so the .f file gets created
if ($stupid and $depend eq "obj") {
$need_f = 1;
}

if ($opt_c && $opt_p) {
die "Doesn't make sense to have both Cray and Parasoft options!";
}

# object file extension
if ($opt_o) {
$obj_ext = $opt_o;
} else {
$obj_ext = 'o';
}

# extension for additional targets (like .prj)
if ($opt_a) {
$add_ext = $opt_a;
}

$mystring = '# DO NOT DELETE THIS LINE - used by make depend';

# Search for the includes in all the files
foreach $file (@ARGV) {
$sources{$file} = new source_file($file, $file);
$sources{$file}->find_includes();
}

# Create new Makefile with new dependencies.

open(MFILE, $mf) || die "can't read Makefile $mf: $!\n";
open(NMFILE, "> Makefile.new") || die "can't write Makefile.new: $!\n";
select(NMFILE);

while (<MFILE>) {
if (!/$mystring/) {
print;
} else {
last;
}
}

print $mystring, "\n";

# Now print out include and use dependencies in sorted order.
foreach $target (sort keys(%sources)) {
$sources{$target}->print();
}

# print out module dependencies
if ( !( $cray || $parasoft) ) {
foreach $modname (sort keys(%mod_files)) {
($name, $path, $suffix) =
&fileparse($sources{$mod_files{$modname}}->{'filepath'}, @suffixes);
$object = $path . "/" . $name . "." . $obj_ext;
print "$modname.$mod_ext: $object\n";
}
}

# Sort out the Makefiles

rename($mf, "$mf.old") || warn "can't overwrite $mf.old: $!\n";
rename('Makefile.new', $mf) ||
warn "can't move Makefile.new to $mf: $!\n";

# Delete those RCS files we checked out
foreach $file (keys %rcs) {
unlink($file);
}

#
# End of main
#

sub findfile {
# Let's see if we can find the included file. Look in current
# directory first, then in directories from -I arguments. Finally,
# look for RCS files in current directory.
my $file = shift;
my($found, $i, $filepath);

$found = 0;

if ( -f $file ) {
$found = 1;
$file =~ s#^\./##; # convert ./foo.h to foo.h
return $file;
}
foreach $i (0 .. $#incdirs) {
$filepath = $incdirs[$i]."/".$file;
if ( -f $filepath ) {
$found = 1;
$filepath =~ s#^\./##; # convert ./foo.h to foo.h
return $filepath;
}
}
#see if it is a checked-in RCS file
if (-f "RCS/$file,v" || -f "$file,v" ) {
$found = 1;
system("co $file");
$filepath = $file;
$rcs{$file} = 1;
}
if ( ! $found ) {
$filepath = "";
}
$filepath;
}

Jos Bergervoet

unread,
Jun 11, 1999, 3:00:00 AM6/11/99
to
bg...@my-dejanews.com wrote:
> dirkj...@my-deja.com writes:

>> I am trying to find an easy way to compile a large (say >50 files)

> <.. use sfmakedepend ..>


> but that's easy to change if really desired. It may be even easier to
> make sfmakedepend issue the compilation commands in the right order.)

Which shows, that 'make' by itself is not adding any real help to this
problem (in contrast to what other posters said?)

-- Jos

Peter S. Shenkin

unread,
Jun 11, 1999, 3:00:00 AM6/11/99
to
FWIW, I use make for everything, including large Fortran projects. I find
it indispensible.

Forget automatic "makedepend" tools. Just keep track manually of what
depends on what. The dependencies change much less frequently than the
code, and once you set things up, incremental changes (e.g., adding a new .f
file with its dependencies) take virtually no time at all.

The one gotcha I should mention is that F90's structure itself is not
ideally suited for make. For many compilers, a file that contains USE
statements for some module really depends only on a module file (like
foo.mod) and not on the module's object file (foo.o); but you can't depend
on this, and even when you can, the naming of the module files can vary from
machine to machine and from compiler to compiler. This complicates support
for multiple compilers or -platforms.

I simply have the using file depend on foo.o in the above example. This can
cause needless recompilations when the module code changes but the
interfaces do not, but it's the safe and simple way to go. Various schemes
have been proposed (including one by me) to overcome this, but I don't
bother.

Also, many platforms have parallel versions of make. This really gets
compilations done in a hurry on an SMP machine.

-P.


Jos Bergervoet <berg...@iaehv.iae.nl> wrote in message
news:7jruvp$51p$1...@news.IAEhv.nl...

Jos Bergervoet

unread,
Jun 12, 1999, 3:00:00 AM6/12/99
to
Peter S. Shenkin <she...@schrodinger.com> wrote:

> The one gotcha I should mention is that F90's structure itself is not
> ideally suited for make. For many compilers, a file that contains USE
> statements for some module really depends only on a module file (like
> foo.mod) and not on the module's object file (foo.o); but you can't depend

But what would it matter? If you have recompiled foo.f90, then both
foo.mod and foo.o will have been updated, so in any case you should
instruct 'make' to recompile other files containing 'USE foo'.

The question of this thread translates to: how to FIND and APPLY these
dependencies for a given set of about 50 files. 'Make' will not find
them! And if you find them by yourself, it would be fairly simple to
program a simple tool to apply them. You can use the 'make' language
for that, but other ways would be just as simple.

So we see that 'make' only solves the easy part. For the difficult part
of the question you have to find other tools.

-- Jos

Peter S. Shenkin

unread,
Jun 12, 1999, 3:00:00 AM6/12/99
to

Jos Bergervoet <berg...@iaehv.iae.nl> wrote in message
news:7jt6go$78$1...@news.IAEhv.nl...
...

> The question of this thread translates to: how to FIND and APPLY these
> dependencies for a given set of about 50 files. 'Make' will not find
> them! And if you find them by yourself, it would be fairly simple to
> program a simple tool to apply them. You can use the 'make' language
> for that, but other ways would be just as simple.
>
> So we see that 'make' only solves the easy part. For the difficult part
> of the question you have to find other tools.

No. Finding and applying these dependencies is the easy part. You do it
once and it's done. It takes an hour for 50 files. Each time you change
some dependency, you fix it in the Makefile. It's very easy.

The hard part is writing the code, not figuring out the dependencies. In
less time than it took you to write all your emails, you could have written
the Makefile for your project.

Of course, if you write code from an IDE, you don't have to do any of
this -- it is all automatic.

-P.


Mike Prager

unread,
Jun 12, 1999, 3:00:00 AM6/12/99
to
On Sat, 12 Jun 1999 11:43:05 -0400, "Peter S. Shenkin"
<she...@schrodinger.com> wrote:

>No. Finding and applying these dependencies is the easy part. You do it
>once and it's done. It takes an hour for 50 files. Each time you change
>some dependency, you fix it in the Makefile. It's very easy.

I agree with the above, and I have found a standard 'make' utility
indispensible for use with Fortran. That includes Fortran with a lot
of modules. Liberal use of macros in the makefile can help.

I use and like a commercial product, Opus make. I tried some of the
Unix ports, but they got confused about native DOS/Windows commands
like 'del' and 'copy'. Perhaps that's improved since I tried them.

Mike Prager
Beaufort, NC

Jos Bergervoet

unread,
Jun 12, 1999, 3:00:00 AM6/12/99
to
Peter S. Shenkin <she...@schrodinger.com> wrote:

> Jos Bergervoet <berg...@iaehv.iae.nl> wrote in message

>> The question of this thread translates to: how to FIND and APPLY these

> No. Finding and applying these dependencies is the easy part. You do it

No. Finding and applying these dependencies was the complete problem of
the OP (original poster).

> once and it's done. It takes an hour for 50 files. Each time you change
> some dependency, you fix it in the Makefile. It's very easy.

Rubbish. After each port to another system, you (or someone else) will be
fiddling with the makefile again.

> The hard part is writing the code, not figuring out the dependencies. In

Writing the code was not the OP's concern (but it may be hard!)

> less time than it took you to write all your emails, you could have written
> the Makefile for your project.

All the emails I ever wrote? I'm sure you're right!

> Of course, if you write code from an IDE, you don't have to do any of

Of course. and if you then port it to another system where this great
IDE is not present?

Greetings,
Jos

Peter S. Shenkin

unread,
Jun 12, 1999, 3:00:00 AM6/12/99
to

Jos Bergervoet <berg...@iaehv.iae.nl> wrote in message
news:7jupdh$l72$1...@news.IAEhv.nl...

> Peter S. Shenkin <she...@schrodinger.com> wrote:
>
> > Jos Bergervoet <berg...@iaehv.iae.nl> wrote in message
> >> The question of this thread translates to: how to FIND and APPLY these
>
> > No. Finding and applying these dependencies is the easy part. You do
it
>
> No. Finding and applying these dependencies was the complete problem of
> the OP (original poster).

I'm saying that if the OP had tried it, he'd have found it isn't so hard. I
had remembered (incorrectly, I guess) that you were the original poster, so
I directed my remarks to you.

> > once and it's done. It takes an hour for 50 files. Each time you
change
> > some dependency, you fix it in the Makefile. It's very easy.
>
> Rubbish. After each port to another system, you (or someone else) will be
> fiddling with the makefile again.

Yes, but not the dependency part. The OP was asking about dependencies.
When you port to a new platform, you don't have to change dependencies
except in very rare cases. You need to change compilation flags and the
like. There are several schemes available for making this easier. As for
putting in the dependencies, putting in platform-specific flags is a bore,
but once it's done, it rarely needs to be altered.

> > Of course, if you write code from an IDE, you don't have to do any of
>
> Of course. and if you then port it to another system where this great
> IDE is not present?

Well, if you port to some other system where some other IDE is present, you
don't have to do the work there, either.

But I don't use IDEs. I use make for much larger projects than a mere fifty
files, and I support these projects on many platforms, with multiple sets of
compilation options for each platform (for instance, for SGI, I have
debugging and optimized branches for both the mips3 and mips4 instruction
set, and for a while I had mips2 branches as well). It's just not that hard
to do, in my actual experience.

There are some things that definitely could be made easier than they are
using make, but adding the dependencies and platform-dependent flags
automatically are not be high on my list. Even for the things that are, I
don't know a better portable alternative than make, and I've never found a
difficulty with make I couldn't work around -- even taking into account the
fact that the way make itself works differs from one platform to another.

-P.


Michael Metcalf

unread,
Jun 17, 1999, 3:00:00 AM6/17/99
to

No, he's talking "makedepend". Dunno whether it can handle, or be
made to
handle, the F90 USE dependencies in addition to INCLUDES.
================================================================

For make files, a perl5 script, which behaves like an X11
makedepend
program (it edits an existing Makefile) and recursively searches
include files for more dependencies, is available from Kate
Hedstrom:
ftp://ahab.rutgers.edu/pub/perl/sfmakedepend
http://marine.rutgers.edu/po/perl.html
For a makemake perl script:
http://www.fortran.com/fortran/makemake.html.


Mike Metcalf

--



0 new messages