rendered paste body#! /usr/local/bin/perl
#
# Usage: makemake {<program name> {<F90 compiler or fc or f77 or cc or c>}}
#
# Generate a Makefile from the sources in the current directory. The source
# files may be in either C, FORTRAN 77, Fortran 90 or some combination of
# these languages. If the F90 compiler specified is cray or parasoft, then
# the Makefile generated will conform to the conventions of these compilers.
# To run makemake, it will be necessary to modify the first line of this script
# to point to the actual location of Perl on your system.
#
# Written by Michael Wester <wester@math.unm.edu> February 16, 1995
# Cotopaxi (Consulting), Albuquerque, New Mexico
#
open(MAKEFILE, "> Makefile");
#
print MAKEFILE "PROG =\t$ARGV[0]\n\n";
#
# Source listing
#
print MAKEFILE "SRCS =\t";
@srcs = <*.f90 *.f *.F *.c>;
&PrintWords(8, 0, @srcs);
print MAKEFILE "\n\n";
#
# Object listing
#
print MAKEFILE "OBJS =\t";
@objs = @srcs;
foreach (@objs) { s/\.[^.]+$/.o/ };
&PrintWords(8, 0, @objs);
print MAKEFILE "\n\n";
#
# Define common macros
#
print MAKEFILE "LIBS =\t\n\n";
print MAKEFILE "CC = gcc\n";
print MAKEFILE "CFLAGS = -O\n";
print MAKEFILE "FC = f77\n";
print MAKEFILE "FFLAGS = -O\n";
print MAKEFILE "F90 = f90\n";
print MAKEFILE "F90FLAGS = -O\n";
print MAKEFILE "LDFLAGS = -s\n\n";
#
# make
#
print MAKEFILE "all: \$(PROG)\n\n";
print MAKEFILE "\$(PROG): \$(OBJS)\n";
print MAKEFILE "\t\$(", &LanguageCompiler($ARGV[1], @srcs);
print MAKEFILE ") \$(LDFLAGS) -o \$@ \$(OBJS) \$(LIBS)\n\n";
#
# make clean
#
print MAKEFILE "clean:\n";
print MAKEFILE "\trm -f \$(PROG) \$(OBJS) *.mod\n\n";
#
# Make .f90 a valid suffix
#
print MAKEFILE ".SUFFIXES: \$(SUFFIXES) .f90\n\n";
#
# .f90 -> .o
#
print MAKEFILE ".f90.o:\n";
print MAKEFILE "\t\$(F90) \$(F90FLAGS) -c \$<\n\n";
#
# Dependency listings
#
&MakeDependsf90($ARGV[1]);
&MakeDepends("*.f *.F", '^\s*include\s+["\']([^"\']+)["\']');
&MakeDepends("*.c", '^\s*#\s*include\s+["\']([^"\']+)["\']');
#
# &PrintWords(current output column, extra tab?, word list); --- print words
# nicely
#
sub PrintWords {
local($columns) = 78 - shift(@_);
local($extratab) = shift(@_);
local($wordlength);
#
print MAKEFILE @_[0];
$columns -= length(shift(@_));
foreach $word (@_) {
$wordlength = length($word);
if ($wordlength + 1 < $columns) {
print MAKEFILE " $word";
$columns -= $wordlength + 1;
}
else {
#
# Continue onto a new line
#
if ($extratab) {
print MAKEFILE " \\\n\t\t$word";
$columns = 62 - $wordlength;
}
else {
print MAKEFILE " \\\n\t$word";
$columns = 70 - $wordlength;
}
}
}
}
#
# &LanguageCompiler(compiler, sources); --- determine the correct language
# compiler
#
sub LanguageCompiler {
local($compiler) = &toLower(shift(@_));
local(@srcs) = @_;
#
if (length($compiler) > 0) {
CASE: {
grep(/^$compiler$/, ("fc", "f77")) &&
do { $compiler = "FC"; last CASE; };
grep(/^$compiler$/, ("cc", "c")) &&
do { $compiler = "CC"; last CASE; };
$compiler = "F90";
}
}
else {
CASE: {
grep(/\.f90$/, @srcs) && do { $compiler = "F90"; last CASE; };
grep(/\.(f|F)$/, @srcs) && do { $compiler = "FC"; last CASE; };
grep(/\.c$/, @srcs) && do { $compiler = "CC"; last CASE; };
$compiler = "???";
}
}
$compiler;
}
#
# &toLower(string); --- convert string into lower case
#
sub toLower {
local($string) = @_[0];
$string =~ tr/A-Z/a-z/;
$string;
}
#
# &uniq(sorted word list); --- remove adjacent duplicate words
#
sub uniq {
local(@words);
foreach $word (@_) {
if ($word ne $words[$#words]) {
push(@words, $word);
}
}
@words;
}
#
# &MakeDepends(language pattern, include file sed pattern); --- dependency
# maker
#
sub MakeDepends {
local(@incs);
local($lang) = @_[0];
local($pattern) = @_[1];
#
foreach $file (<${lang}>) {
open(FILE, $file) || warn "Cannot open $file: $!\n";
while (<FILE>) {
/$pattern/i && push(@incs, $1);
}
if (defined @incs) {
$file =~ s/\.[^.]+$/.o/;
print MAKEFILE "$file: ";
&PrintWords(length($file) + 2, 0, @incs);
print MAKEFILE "\n";
undef @incs;
}
}
}
#
# &MakeDependsf90(f90 compiler); --- FORTRAN 90 dependency maker
#
sub MakeDependsf90 {
local($compiler) = &toLower(@_[0]);
local(@dependencies);
local(%filename);
local(@incs);
local(@modules);
local($objfile);
#
# Associate each module with the name of the file that contains it
#
foreach $file (<*.f90>) {
open(FILE, $file) || warn "Cannot open $file: $!\n";
while (<FILE>) {
/^\s*module\s+([^\s!]+)/i &&
($filename{&toLower($1)} = $file) =~ s/\.f90$/.o/;
}
}
#
# Print the dependencies of each file that has one or more include's or
# references one or more modules
#
foreach $file (<*.f90>) {
open(FILE, $file);
while (<FILE>) {
/^\s*include\s+["\']([^"\']+)["\']/i && push(@incs, $1);
/^\s*use\s+([^\s,!]+)/i && push(@modules, &toLower($1));
}
if (defined @incs || defined @modules) {
($objfile = $file) =~ s/\.f90$/.o/;
print MAKEFILE "$objfile: ";
undef @dependencies;
foreach $module (@modules) {
push(@dependencies, $filename{$module});
}
@dependencies = &uniq(sort(@dependencies));
&PrintWords(length($objfile) + 2, 0,
@dependencies, &uniq(sort(@incs)));
print MAKEFILE "\n";
undef @incs;
undef @modules;
#
# Cray F90 compiler
#
if ($compiler eq "cray") {
print MAKEFILE "\t\$(F90) \$(F90FLAGS) -c ";
foreach $depend (@dependencies) {
push(@modules, "-p", $depend);
}
push(@modules, $file);
&PrintWords(30, 1, @modules);
print MAKEFILE "\n";
undef @modules;
}
#
# ParaSoft F90 compiler
#
if ($compiler eq "parasoft") {
print MAKEFILE "\t\$(F90) \$(F90FLAGS) -c ";
foreach $depend (@dependencies) {
$depend =~ s/\.o$/.f90/;
push(@modules, "-module", $depend);
}
push(@modules, $file);
&PrintWords(30, 1, @modules);
print MAKEFILE "\n";
undef @modules;
}
}
}
}