1 |
#! /usr/bin/perl |
2 |
# |
3 |
# Usage: makemake {<program name> {<F90 compiler or fc or f77 or cc or c>}} |
4 |
# |
5 |
# Generate a Makefile from the sources in the current directory. The source |
6 |
# files may be in either C, FORTRAN 77, Fortran 90 or some combination of |
7 |
# these languages. If the F90 compiler specified is cray or parasoft, then |
8 |
# the Makefile generated will conform to the conventions of these compilers. |
9 |
# To run makemake, it will be necessary to modify the first line of this script |
10 |
# to point to the actual location of Perl on your system. |
11 |
# |
12 |
# Written by Michael Wester <wester@math.unm.edu> December 27, 1995 |
13 |
# Cotopaxi (Consulting), Albuquerque, New Mexico |
14 |
# |
15 |
open(MAKEFILE, "> Makefile"); |
16 |
# |
17 |
print MAKEFILE "include Makefile.local\n\n"; |
18 |
print MAKEFILE "PROG =\t$ARGV[0]\n\n"; |
19 |
# |
20 |
# Allow Fortran 90 module source files to have extensions other than .f90 |
21 |
# |
22 |
$mod_ext = F90; |
23 |
@f90 = uniq(f90, $mod_ext); |
24 |
foreach (@f90) { s/^/*./ }; |
25 |
# |
26 |
# Source listing |
27 |
# |
28 |
print MAKEFILE "SRCS =\t"; |
29 |
@srcs = <@f90 *.f *.F *.c>; |
30 |
&PrintWords(8, 0, @srcs); |
31 |
print MAKEFILE "\n\n"; |
32 |
# |
33 |
# Object listing |
34 |
# |
35 |
print MAKEFILE "OBJS =\t"; |
36 |
@objs = @srcs; |
37 |
foreach (@objs) { s/\.[^.]+$/.o/ }; |
38 |
&PrintWords(8, 0, @objs); |
39 |
print MAKEFILE "\n\n"; |
40 |
# |
41 |
# |
42 |
# Define common macros |
43 |
# These are defined in Makefile.local which provides custom settings |
44 |
# for a particular system. |
45 |
# |
46 |
# print MAKEFILE "# LIBS =\t\n\n"; |
47 |
# print MAKEFILE "# CC = cc\n"; |
48 |
# print MAKEFILE "# CFLAGS = -O\n"; |
49 |
# print MAKEFILE "# FC = f77\n"; |
50 |
# print MAKEFILE "# FFLAGS = -O\n"; |
51 |
# print MAKEFILE "# F90 = f90\n"; |
52 |
# print MAKEFILE "# F90FLAGS = -O\n"; |
53 |
# print MAKEFILE "# LDFLAGS = -s\n\n"; |
54 |
# |
55 |
# make |
56 |
# |
57 |
print MAKEFILE "all: lib\$(PROG).a\n\n"; |
58 |
print MAKEFILE "\$(PROG): \$(OBJS)\n"; |
59 |
print MAKEFILE "\t\$(", &LanguageCompiler($ARGV[1], @srcs); |
60 |
print MAKEFILE ") \$(LDFLAGS) -o \$@ \$(OBJS) \$(LIBS)\n\n"; |
61 |
print MAKEFILE "lib\$(PROG).a: \$(OBJS)\n"; |
62 |
print MAKEFILE "\t\$(AR)"; |
63 |
print MAKEFILE " \$(ARFLAGS) \$@ \$(OBJS)\n"; |
64 |
# |
65 |
# make clean |
66 |
# |
67 |
print MAKEFILE "clean:\n"; |
68 |
print MAKEFILE "\trm -f \$(PROG) \$(OBJS) *.mod lib\$(PROG).a install_mod install_lib\n\n"; |
69 |
# |
70 |
# make install |
71 |
# |
72 |
print MAKEFILE "install: install_lib install_mod\n\n"; |
73 |
print MAKEFILE "install_lib: lib\$(PROG).a\n"; |
74 |
print MAKEFILE "\tcp"; |
75 |
print MAKEFILE " \$< ../../lib\n"; |
76 |
print MAKEFILE "\ttouch"; |
77 |
print MAKEFILE " \install_lib\n\n"; |
78 |
print MAKEFILE "install_mod: \$(OBJS)\n"; |
79 |
print MAKEFILE "\tcp"; |
80 |
print MAKEFILE " \*.mod ../../mod\n"; |
81 |
print MAKEFILE "\ttouch"; |
82 |
print MAKEFILE " \install_mod\n\n"; |
83 |
# |
84 |
# Make .f90 a valid suffix |
85 |
# |
86 |
print MAKEFILE ".SUFFIXES: \$(SUFFIXES) .f90"; |
87 |
if ($mod_ext ne "f90") { print MAKEFILE " .$mod_ext"; }; |
88 |
print MAKEFILE "\n\n"; |
89 |
# |
90 |
# .f90 -> .o |
91 |
# |
92 |
print MAKEFILE ".f90.o:\n"; |
93 |
print MAKEFILE "\t\$(F90) \$(F90FLAGS) -c \$<\n\n"; |
94 |
# |
95 |
# .$mod_ext -> .o |
96 |
# |
97 |
if ($mod_ext ne "f90") { |
98 |
print MAKEFILE ".$mod_ext.o:\n"; |
99 |
print MAKEFILE "\t\$(F90) \$(F90FLAGS) -c \$<\n\n"; |
100 |
} |
101 |
# |
102 |
# Dependency listings |
103 |
# |
104 |
&MakeDependsf90($ARGV[1]); |
105 |
&MakeDepends("*.f *.F", '^\s*include\s+["\']([^"\']+)["\']'); |
106 |
&MakeDepends("*.c", '^\s*#\s*include\s+["\']([^"\']+)["\']'); |
107 |
|
108 |
# |
109 |
# &PrintWords(current output column, extra tab?, word list); --- print words |
110 |
# nicely |
111 |
# |
112 |
sub PrintWords { |
113 |
local($columns) = 78 - shift(@_); |
114 |
local($extratab) = shift(@_); |
115 |
local($wordlength); |
116 |
# |
117 |
print MAKEFILE @_[0]; |
118 |
$columns -= length(shift(@_)); |
119 |
foreach $word (@_) { |
120 |
$wordlength = length($word); |
121 |
if ($wordlength + 1 < $columns) { |
122 |
print MAKEFILE " $word"; |
123 |
$columns -= $wordlength + 1; |
124 |
} |
125 |
else { |
126 |
# |
127 |
# Continue onto a new line |
128 |
# |
129 |
if ($extratab) { |
130 |
print MAKEFILE " \\\n\t\t$word"; |
131 |
$columns = 62 - $wordlength; |
132 |
} |
133 |
else { |
134 |
print MAKEFILE " \\\n\t$word"; |
135 |
$columns = 70 - $wordlength; |
136 |
} |
137 |
} |
138 |
} |
139 |
} |
140 |
|
141 |
# |
142 |
# &LanguageCompiler(compiler, sources); --- determine the correct language |
143 |
# compiler |
144 |
# |
145 |
sub LanguageCompiler { |
146 |
local($compiler) = &toLower(shift(@_)); |
147 |
local(@srcs) = @_; |
148 |
# |
149 |
if (length($compiler) > 0) { |
150 |
CASE: { |
151 |
grep(/^$compiler$/, ("fc", "f77")) && |
152 |
do { $compiler = "FC"; last CASE; }; |
153 |
grep(/^$compiler$/, ("cc", "c")) && |
154 |
do { $compiler = "CC"; last CASE; }; |
155 |
$compiler = "F90"; |
156 |
} |
157 |
} |
158 |
else { |
159 |
CASE: { |
160 |
grep(/\.f90$/, @srcs) && do { $compiler = "F90"; last CASE; }; |
161 |
grep(/\.F90$/, @srcs) && do { $compiler = "F90"; last CASE; }; |
162 |
grep(/\.(f|F)$/, @srcs) && do { $compiler = "FC"; last CASE; }; |
163 |
grep(/\.c$/, @srcs) && do { $compiler = "CC"; last CASE; }; |
164 |
$compiler = "???"; |
165 |
} |
166 |
} |
167 |
$compiler; |
168 |
} |
169 |
|
170 |
# |
171 |
# &toLower(string); --- convert string into lower case |
172 |
# |
173 |
sub toLower { |
174 |
local($string) = @_[0]; |
175 |
$string =~ tr/A-Z/a-z/; |
176 |
$string; |
177 |
} |
178 |
|
179 |
# |
180 |
# &uniq(sorted word list); --- remove adjacent duplicate words |
181 |
# |
182 |
sub uniq { |
183 |
local(@words); |
184 |
foreach $word (@_) { |
185 |
if ($word ne $words[$#words]) { |
186 |
push(@words, $word); |
187 |
} |
188 |
} |
189 |
@words; |
190 |
} |
191 |
|
192 |
# |
193 |
# &MakeDepends(language pattern, include file sed pattern); --- dependency |
194 |
# maker |
195 |
# |
196 |
sub MakeDepends { |
197 |
local(@incs); |
198 |
local($lang) = @_[0]; |
199 |
local($pattern) = @_[1]; |
200 |
# |
201 |
foreach $file (<${lang}>) { |
202 |
open(FILE, $file) || warn "Cannot open $file: $!\n"; |
203 |
while (<FILE>) { |
204 |
/$pattern/i && push(@incs, $1); |
205 |
} |
206 |
if (defined @incs) { |
207 |
$file =~ s/\.[^.]+$/.o/; |
208 |
print MAKEFILE "$file: "; |
209 |
&PrintWords(length($file) + 2, 0, @incs); |
210 |
print MAKEFILE "\n"; |
211 |
undef @incs; |
212 |
} |
213 |
} |
214 |
} |
215 |
|
216 |
# |
217 |
# &MakeDependsf90(f90 compiler); --- FORTRAN 90 dependency maker |
218 |
# |
219 |
sub MakeDependsf90 { |
220 |
local($compiler) = &toLower(@_[0]); |
221 |
local(@dependencies); |
222 |
local(%filename); |
223 |
local(@incs); |
224 |
local(@modules); |
225 |
local($objfile); |
226 |
# |
227 |
# Associate each module with the name of the file that contains it |
228 |
# |
229 |
foreach $file (<*.$mod_ext>) { |
230 |
open(FILE, $file) || warn "Cannot open $file: $!\n"; |
231 |
while (<FILE>) { |
232 |
/^\s*module\s+([^\s!]+)/i && |
233 |
($filename{&toLower($1)} = $file) =~ s/\.$mod_ext$/.o/; |
234 |
} |
235 |
} |
236 |
# |
237 |
# Print the dependencies of each file that has one or more include's or |
238 |
# references one or more modules |
239 |
# |
240 |
foreach $file (<@f90>) { |
241 |
open(FILE, $file); |
242 |
while (<FILE>) { |
243 |
/^\s*include\s+["\']([^"\']+)["\']/i && push(@incs, $1); |
244 |
/^\s*use\s+([^\s,!]+)/i && push(@modules, &toLower($1)); |
245 |
} |
246 |
if (defined @incs || defined @modules) { |
247 |
($objfile = $file) =~ s/\.[^.]+$/.o/; |
248 |
print MAKEFILE "$objfile: "; |
249 |
undef @dependencies; |
250 |
foreach $module (@modules) { |
251 |
push(@dependencies, $filename{$module}); |
252 |
} |
253 |
@dependencies = &uniq(sort(@dependencies)); |
254 |
&PrintWords(length($objfile) + 2, 0, |
255 |
@dependencies, &uniq(sort(@incs))); |
256 |
print MAKEFILE "\n"; |
257 |
undef @incs; |
258 |
undef @modules; |
259 |
# |
260 |
# Cray F90 compiler |
261 |
# |
262 |
if ($compiler eq "cray") { |
263 |
print MAKEFILE "\t\$(F90) \$(F90FLAGS) -c "; |
264 |
foreach $depend (@dependencies) { |
265 |
push(@modules, "-p", $depend); |
266 |
} |
267 |
push(@modules, $file); |
268 |
&PrintWords(30, 1, @modules); |
269 |
print MAKEFILE "\n"; |
270 |
undef @modules; |
271 |
} |
272 |
# |
273 |
# ParaSoft F90 compiler |
274 |
# |
275 |
if ($compiler eq "parasoft") { |
276 |
print MAKEFILE "\t\$(F90) \$(F90FLAGS) -c "; |
277 |
foreach $depend (@dependencies) { |
278 |
$depend =~ s/\.o$/.f90/; |
279 |
push(@modules, "-module", $depend); |
280 |
} |
281 |
push(@modules, $file); |
282 |
&PrintWords(30, 1, @modules); |
283 |
print MAKEFILE "\n"; |
284 |
undef @modules; |
285 |
} |
286 |
} |
287 |
} |
288 |
} |
289 |
|