1 |
cnh |
1.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 |
|
|
|