1 |
#! /usr/bin/perl -w |
2 |
# ex:ts=4 |
3 |
# |
4 |
# portlint - lint for port directory |
5 |
# implemented by: |
6 |
# Jun-ichiro itojun Hagino <itojun@itojun.org> |
7 |
# Yoshishige Arai <ryo2@on.rim.or.jp> |
8 |
# |
9 |
# Copyright(c) 1997 by Jun-ichiro Hagino <itojun@itojun.org>. |
10 |
# All rights reserved. |
11 |
# Freely redistributable. Absolutely no warranty. |
12 |
# |
13 |
# Please note that this perl code used to be able to handle (Open|Net|Free)BSD |
14 |
# bsd.port.mk. There are significant differences in those so non-FreeBSD code |
15 |
# was removed. |
16 |
# |
17 |
# $MidnightBSD: mports/ports-mgmt/portlint/src/portlint.pl,v 1.11 2013/01/18 03:56:21 laffer1 Exp $ |
18 |
# $FreeBSD: ports/devel/portlint/src/portlint.pl,v 1.91 2006/08/06 22:36:45 marcus Exp $ |
19 |
# |
20 |
|
21 |
use strict; |
22 |
use warnings; |
23 |
|
24 |
use Getopt::Std; |
25 |
use File::Find; |
26 |
use IPC::Open2; |
27 |
use File::Basename; |
28 |
use POSIX qw(strftime); |
29 |
|
30 |
sub perror($$$$); |
31 |
our ($opt_a, $opt_A, $opt_b, $opt_C, $opt_c, $opt_g, $opt_h, $opt_m, $opt_t, $opt_v, $opt_M, $opt_N, $opt_B, $opt_V, @ALLOWED_FULL_PATHS); |
32 |
|
33 |
my ($err, $warn); |
34 |
my ($extrafile, $parenwarn, $committer, $verbose, $usetabs, $newport, |
35 |
$grouperrs, $checkmfiles); |
36 |
my $contblank; |
37 |
my $portdir; |
38 |
my $makeenv = ""; |
39 |
my @errlst = (); |
40 |
my %errcache = (); |
41 |
|
42 |
$err = $warn = 0; |
43 |
$extrafile = $parenwarn = $committer = $verbose = $usetabs = $newport = 0; |
44 |
$checkmfiles = 0; |
45 |
$contblank = 1; |
46 |
$portdir = '.'; |
47 |
|
48 |
@ALLOWED_FULL_PATHS = qw(/boot/loader.conf /compat/ /dev/null /etc/inetd.conf); |
49 |
|
50 |
# version variables |
51 |
my $major = 2; |
52 |
my $minor = 18; |
53 |
my $micro = 3; |
54 |
|
55 |
# default setting - for MidnightBSD |
56 |
my $portsdir = '/usr/mports'; |
57 |
my $rcsidstr = 'MidnightBSD'; |
58 |
my $localbase = '/usr/local'; |
59 |
my $numpitems = 6; |
60 |
|
61 |
my %lang_pref = qw( |
62 |
arabic ar |
63 |
chinese zh |
64 |
french fr |
65 |
german de |
66 |
hebrew iw |
67 |
hungarian hu |
68 |
japanese ja |
69 |
korean ko |
70 |
polish pl |
71 |
portuguese pt |
72 |
russian ru |
73 |
ukrainian uk |
74 |
vietnamese vi |
75 |
); |
76 |
my @lang_cat = keys %lang_pref; |
77 |
my @lang_short = values %lang_pref; |
78 |
my $re_lang_short = '(' . join('|', @lang_short) . ')-'; |
79 |
|
80 |
my ($prog) = ($0 =~ /([^\/]+)$/); |
81 |
sub usage { |
82 |
print STDERR <<EOF; |
83 |
usage: $prog [-AabCcghmvtN] [-M ENV] [-B#] [port_directory] |
84 |
-a additional check for scripts/* and pkg-* |
85 |
-A turn on all additional checks (equivalent to -abcmNt) |
86 |
-b warn \$(VARIABLE) |
87 |
-c committer mode (implies -m) |
88 |
-C pedantic committer mode (equivalent to -abcmt) |
89 |
-g group errors together to avoid duplication (disabled if -v is specified) |
90 |
-h show summary of command line options |
91 |
-v verbose mode |
92 |
-t nit pick about use of spaces |
93 |
-m check \${PORTSDIR}/MOVED, UIDs, and GIDs files |
94 |
-N writing a new port |
95 |
-V print the version and exit |
96 |
-M ENV set make variables to ENV (ex. PORTSDIR=/usr/mports.work) |
97 |
-B# allow # contiguous blank lines (default: $contblank line) |
98 |
EOF |
99 |
exit 0; |
100 |
} |
101 |
|
102 |
sub version { |
103 |
print "$prog version $major.$minor.$micro\n"; |
104 |
exit $major; |
105 |
} |
106 |
|
107 |
getopts('AabCcghmtvB:M:NV'); |
108 |
|
109 |
&usage if $opt_h; |
110 |
&version if $opt_V; |
111 |
$extrafile = 1 if $opt_a || $opt_A || $opt_C; |
112 |
$parenwarn = 1 if $opt_b || $opt_A || $opt_C; |
113 |
$committer = 1 if $opt_c || $opt_A || $opt_C; |
114 |
$verbose = 1 if $opt_v; |
115 |
$grouperrs = 1 if $opt_g && !$opt_v; |
116 |
$checkmfiles = 1 if $opt_m || $opt_c || $opt_A || $opt_C; |
117 |
$newport = 1 if $opt_N || $opt_A; |
118 |
$usetabs = 1 if $opt_t || $opt_A || $opt_C; |
119 |
$contblank = $opt_B if $opt_B; |
120 |
$makeenv = $opt_M if $opt_M; |
121 |
|
122 |
$portdir = $ARGV[0] ? $ARGV[0] : '.'; |
123 |
|
124 |
# The PORTSDIR environment variable overrides our defaults. |
125 |
$portsdir = $ENV{PORTSDIR} if ( defined $ENV{'PORTSDIR'} ); |
126 |
$ENV{'PL_SVN_IGNORE'} //= ''; |
127 |
my $mfile_moved = "${portsdir}/MOVED"; |
128 |
my $mfile_uids = "${portsdir}/UIDs"; |
129 |
my $mfile_gids = "${portsdir}/GIDs"; |
130 |
|
131 |
if ($verbose) { |
132 |
print "OK: config: portsdir: \"$portsdir\" ". |
133 |
"rcsidstr: \"$rcsidstr\" ". |
134 |
"localbase: $localbase ". |
135 |
"\n"; |
136 |
} |
137 |
|
138 |
# |
139 |
# just for safety. |
140 |
# |
141 |
if (! -d $portdir) { |
142 |
print STDERR "FATAL: invalid directory $portdir specified.\n"; |
143 |
exit 1; |
144 |
} |
145 |
|
146 |
chdir "$portdir" || die "$portdir: $!"; |
147 |
|
148 |
# get make vars |
149 |
my @varlist = qw( |
150 |
PORTNAME PORTVERSION PORTREVISION PORTEPOCH PKGNAME PKGNAMEPREFIX |
151 |
PKGNAMESUFFIX DISTVERSIONPREFIX DISTVERSION DISTVERSIONSUFFIX |
152 |
DISTNAME DISTFILES CATEGORIES MASTERDIR MAINTAINER MASTER_SITES |
153 |
WRKDIR WRKSRC NO_WRKSUBDIR SCRIPTDIR FILESDIR |
154 |
PKGDIR COMMENT DESCR PLIST PKGCATEGORY PKGINSTALL PKGDEINSTALL |
155 |
PKGREQ PKGMESSAGE DISTINFO_FILE .CURDIR USE_LDCONFIG USE_AUTOTOOLS |
156 |
USE_GNOME USE_PERL5 USE_QT5 INDEXFILE PKGORIGIN CONFLICTS PKG_VERSION |
157 |
PLIST_FILES PLIST_DIRS PORTDOCS PORTEXAMPLES |
158 |
OPTIONS_DEFINE OPTIONS_RADIO OPTIONS_SINGLE OPTIONS_MULTI |
159 |
OPTIONS_GROUP OPTIONS_SUB INSTALLS_OMF USE_RC_SUBR USES DIST_SUBDIR |
160 |
ALLFILES CHECKSUM_ALGORITHMS INSTALLS_ICONS GNU_CONFIGURE |
161 |
CONFIGURE_ARGS MASTER_SITE_SUBDIR LICENSE LICENSE_COMB NO_STAGE |
162 |
DEVELOPER SUB_FILES SHEBANG_LANG MASTER_SITES_SUBDIRS FLAVORS |
163 |
USE_PYTHON |
164 |
); |
165 |
|
166 |
my %makevar; |
167 |
my $i = 0; |
168 |
for (split(/\n/, get_makevar(@varlist))) { |
169 |
$_ =~ s/\0//; |
170 |
print "OK: makevar: $varlist[$i] = $_\n" if ($verbose); |
171 |
$makevar{$varlist[$i]} = $_; |
172 |
$i++; |
173 |
} |
174 |
|
175 |
# |
176 |
# variables for global checks. |
177 |
# |
178 |
my $sharedocused = 0; |
179 |
|
180 |
my %predefined = (); |
181 |
|
182 |
my @popt = (); |
183 |
|
184 |
# historical, no longer in FreeBSD's bsd.sites.mk |
185 |
foreach my $i (split(/\n/, <<EOF)) { |
186 |
GNU ftp://prep.ai.mit.edu/pub/gnu/%SUBDIR%/ |
187 |
SUNSITE ftp://sunsite.unc.edu/pub/Linux/%SUBDIR%/ |
188 |
EOF |
189 |
my ($j, $k) = split(/\t+/, $i); |
190 |
$predefined{$k} = $j; |
191 |
} |
192 |
|
193 |
# Read bsd.sites.mk |
194 |
my $sites_mk = "$portsdir/Mk/components/sites.mk"; |
195 |
open(MK, $sites_mk) || die "$sites_mk: $!"; |
196 |
my @site_groups = grep($_ = /^MASTER_SITE_(\w+)/ && $1, <MK>); |
197 |
close(MK); |
198 |
|
199 |
my $cmd = join(' -V MASTER_SITE_', "make $makeenv ", @site_groups); |
200 |
|
201 |
$i = 0; |
202 |
|
203 |
open2(\*IN, \*OUT, $cmd); |
204 |
|
205 |
close(OUT); |
206 |
|
207 |
while (<IN>) { |
208 |
my $g = $site_groups[$i]; |
209 |
for my $s (split()) { |
210 |
$predefined{$s} = $g; |
211 |
} |
212 |
$i++; |
213 |
} |
214 |
|
215 |
close(IN); |
216 |
|
217 |
open(MK, 'Makefile') || die "Makefile: $!"; |
218 |
my $ulineno = -1; |
219 |
my $uulineno = -1; |
220 |
my @muses = (); |
221 |
while (my $mline = <MK>) { |
222 |
if ($uulineno == -1 && $mline =~ /^USE_/) { |
223 |
$uulineno = $.; |
224 |
} |
225 |
if ($mline =~ /^USES[?+]?=\s*(.*)/) { |
226 |
if ($ulineno == -1) { |
227 |
$ulineno = $.; |
228 |
} |
229 |
if ($1) { |
230 |
push @muses, split(/\s+/, $1); |
231 |
} |
232 |
} |
233 |
} |
234 |
if ($uulineno > -1 && $ulineno > -1 && $uulineno < $ulineno) { |
235 |
&perror("WARN", 'Makefile', $uulineno, "USE_* seen before USES. ". |
236 |
"According to the porters-handbook, USES must appear first."); |
237 |
} |
238 |
foreach my $muse (@muses) { |
239 |
$makevar{USES} .= " " . $muse; |
240 |
} |
241 |
|
242 |
# |
243 |
# check for files. |
244 |
# |
245 |
my @checker = ($makevar{DESCR}, 'Makefile', $makevar{DISTINFO_FILE}); |
246 |
my %checker = ( |
247 |
$makevar{DESCR} => \&checkdescr, |
248 |
'Makefile' => \&checkmakefile, |
249 |
$makevar{DISTINFO_FILE} => \&checkdistinfo |
250 |
); |
251 |
if ($extrafile) { |
252 |
my @files = ( |
253 |
<$makevar{SCRIPTDIR}/*>, |
254 |
@makevar{qw(DESCR PLIST PKGINSTALL PKGDEINSTALL PKGREQ PKGMESSAGE)} |
255 |
); |
256 |
|
257 |
foreach my $i (@files) { |
258 |
next if (! -T $i); |
259 |
next if (defined $checker{$i}); |
260 |
if ($i =~ /\bpkg-plist/) { |
261 |
unshift(@checker, $i); |
262 |
$checker{$i} = \&checkplist; |
263 |
} else { |
264 |
push(@checker, $i); |
265 |
$checker{$i} = \&checkpathname; |
266 |
} |
267 |
} |
268 |
} |
269 |
if ($checkmfiles) { |
270 |
foreach my $i ($mfile_moved, $mfile_uids, $mfile_gids) { |
271 |
next if (! -T $i); |
272 |
next if (defined $checker{$i}); |
273 |
push(@checker, $i); |
274 |
$checker{$i} = \&checkmfile; |
275 |
} |
276 |
} |
277 |
foreach my $i (<$makevar{FILESDIR}/patch-*>) { |
278 |
next if (! -T $i); |
279 |
next if (defined $checker{$i}); |
280 |
push(@checker, $i); |
281 |
$checker{$i} = \&checkpatch; |
282 |
} |
283 |
foreach my $i (@checker) { |
284 |
print "OK: checking $i.\n" if ($verbose); |
285 |
if (! -f "$i") { |
286 |
&perror("FATAL", "", -1, "no $i in \"$portdir\".") unless $i eq $makevar{DISTINFO_FILE} && $makevar{DISTFILES} eq ""; |
287 |
} else { |
288 |
my $proc = $checker{$i}; |
289 |
&$proc($i) || &perror("", "", -1, "Cannot open the file $i\n"); |
290 |
if ($proc ne \&checkpatch) { |
291 |
&checklastline($i) |
292 |
|| &perror("", "", -1, "Cannot open the file $i\n"); |
293 |
} |
294 |
} |
295 |
} |
296 |
|
297 |
if ($committer) { |
298 |
sub find_proc { |
299 |
return if /^\.\.?$/; |
300 |
|
301 |
(my $fullname = $File::Find::name) =~ s#^\./##; |
302 |
|
303 |
print "OK: checking the file name of $fullname.\n" if ($verbose); |
304 |
|
305 |
if ($fullname eq 'work') { |
306 |
&perror("FATAL", $fullname, -1, "be sure to cleanup the working directory ". |
307 |
"before committing the port."); |
308 |
|
309 |
$File::Find::prune = 1; |
310 |
} elsif (-l) { |
311 |
&perror("WARN", $fullname, -1, "this is a symlink. ". |
312 |
"Please remove it."); |
313 |
} elsif (-z) { |
314 |
&perror("FATAL", $fullname, -1, "empty file and should be removed. ". |
315 |
"If it still needs to be there, put a dummy comment ". |
316 |
"to state that the file is intentionally left empty."); |
317 |
} elsif (-d && scalar(my @x = <$_/{*,.?*}>) <= 1) { |
318 |
&perror("FATAL", $fullname, -1, "empty directory should be removed.") unless ($fullname =~ /^\.svn/ || $fullname =~ /^\.git/); |
319 |
} elsif (/^\./) { |
320 |
&perror("WARN", $fullname, -1, "dotfiles are not preferred. ". |
321 |
"If this file is a dotfile to be installed as an example, ". |
322 |
"consider importing it as \"dot$_\".") unless |
323 |
(-d && ($_ eq '.svn' || $_ eq '.git')); |
324 |
} elsif (/[^-.a-zA-Z0-9_\+]/) { |
325 |
&perror("WARN", $fullname, -1, "only use characters ". |
326 |
"[-_.a-zA-Z0-9+] for patch or script names."); |
327 |
} elsif (/\.(orig|rej|bak)$/ || /~$/ || /^\#/) { |
328 |
&perror("FATAL", $fullname, -1, "for safety, be sure to cleanup ". |
329 |
"backup files before committing the port."); |
330 |
} elsif (/(^|\.)core$/) { |
331 |
&perror("FATAL", $fullname, -1, "for safety, be sure to cleanup ". |
332 |
"core files before committing the port."); |
333 |
} elsif (/README.html/) { |
334 |
&perror("FATAL", $fullname, -1, "for safety, be sure to cleanup ". |
335 |
"README.html files before committing the port."); |
336 |
} elsif (($_ eq '.svn' || $_ eq '.git') && -d) { |
337 |
&perror("FATAL", $fullname, -1, "for safety, be sure to cleanup ". |
338 |
"Subversion files before committing the port."); |
339 |
|
340 |
$File::Find::prune = 1; |
341 |
} elsif ($_ eq 'CVS' && -d) { |
342 |
if ($newport) { |
343 |
&perror("FATAL", $fullname, -1, "for safety, be sure to cleanup ". |
344 |
"CVS directories before importing the new port."); |
345 |
} |
346 |
|
347 |
$File::Find::prune = 1; |
348 |
} elsif (-f) { |
349 |
my $fullpath = $makevar{'.CURDIR'}.'/'.$fullname; |
350 |
my $result = `type svn >/dev/null 2>&1 && svn -q status $fullpath`; |
351 |
|
352 |
chomp $result; |
353 |
if (substr($result, 0, 1) eq '?') { |
354 |
&perror("FATAL", "", -1, "$fullname not under SVN.") |
355 |
unless (eval { /$ENV{'PL_SVN_IGNORE'}/, 1 } && |
356 |
/$ENV{'PL_SVN_IGNORE'}/); |
357 |
} |
358 |
} |
359 |
} |
360 |
|
361 |
find(\&find_proc, '.'); |
362 |
|
363 |
# Check for ports that may break INDEX |
364 |
my $indexerr = `env LOCALBASE=/nonexistentlocal make $makeenv describe 2>&1 >/dev/null`; |
365 |
chomp $indexerr; |
366 |
$indexerr =~ tr/\n/ /s; |
367 |
&perror("FATAL", "", -1, "breaks INDEX ($indexerr).") |
368 |
if ($indexerr); |
369 |
# Suggest to set MPORT_MAINTAINER_MODE knob in /etc/make.conf |
370 |
if (!$makevar{MPORT_MAINTAINER_MODE}) { |
371 |
&perror("WARN", "", -1, "Consider to set MPORT_MAINTAINER_MODE=yes in /etc/make.conf"); |
372 |
} |
373 |
} |
374 |
if ($err || $warn) { |
375 |
my($errtext, $warntext) = ("error", "warning"); |
376 |
$errtext .= "s" unless ($err == 1); |
377 |
$warntext .= "s" unless ($warn == 1); |
378 |
if ($grouperrs) { |
379 |
foreach my $msg (@errlst) { |
380 |
my $lines; |
381 |
if ($errcache{$msg} && scalar(@{$errcache{$msg}})) { |
382 |
$lines = "[" . (join(",", @{$errcache{$msg}})) . "]: "; |
383 |
} else { |
384 |
$lines = ""; |
385 |
} |
386 |
$msg =~ s/%%LINES%%/$lines/; |
387 |
print $msg, "\n"; |
388 |
} |
389 |
} |
390 |
printf("%d fatal %s and %d %s found.\n", $err, $errtext, $warn, $warntext); |
391 |
} else { |
392 |
print "looks fine.\n"; |
393 |
} |
394 |
exit $err; |
395 |
|
396 |
# |
397 |
# distinfo |
398 |
# |
399 |
sub checkdistinfo { |
400 |
my($file) = @_; |
401 |
my($dist_subdir) = $makevar{DIST_SUBDIR}; |
402 |
my(@allfiles) = split (/\s+/, $makevar{ALLFILES}); |
403 |
my %algorithms = (); |
404 |
my %records = (); |
405 |
|
406 |
foreach my $i (split (/\s+/, uc ($makevar{CHECKSUM_ALGORITHMS}))) { |
407 |
$algorithms{$i} = 1; |
408 |
} |
409 |
|
410 |
open(IN, "< $file") || return 0; |
411 |
while (<IN>) { |
412 |
if (/^\s*$/) { |
413 |
&perror("FATAL", $file, $., "found blank line."); |
414 |
next; |
415 |
} |
416 |
if (/^TIMESTAMP\s+=\s+(\d+)$/) { |
417 |
my $now = time; |
418 |
if ($1 > $now) { |
419 |
&perror("FATAL", $file, $., "TIMESTAMP is in the future"); |
420 |
} |
421 |
next; |
422 |
} |
423 |
if (/(\S+)\s+\((\S+)\)\s+=\s+(\S+)/) { |
424 |
my ($tag, $path, $value) = ($1, $2, $3); |
425 |
$records{$path}{$tag} = $value; |
426 |
|
427 |
if (!$algorithms{$tag} && $tag ne "SIZE") { |
428 |
&perror("FATAL", $file, $., "unsupported checksum algorithm ". |
429 |
"found: $tag."); |
430 |
} |
431 |
} else { |
432 |
&perror("FATAL", $file, $., "line format error."); |
433 |
} |
434 |
} |
435 |
close(IN); |
436 |
|
437 |
# For all files check SIZE and checksums |
438 |
foreach my $f (@allfiles) { |
439 |
# Remove hindering chars from DISTNAME |
440 |
$f =~ s/['\\]//g; |
441 |
|
442 |
my $path = $f; |
443 |
$path = "$dist_subdir/$f" if $dist_subdir; |
444 |
if (!defined($records{$path}{SIZE})) { |
445 |
&perror("FATAL", $file, -1, "has no SIZE record for $path."); |
446 |
} |
447 |
my $n = 0; |
448 |
foreach my $alg (keys %algorithms) { |
449 |
$n++ if exists($records{$path}{$alg}); |
450 |
} |
451 |
if ($n == 0) { |
452 |
&perror("FATAL", $file, -1, "no checksum record for $path."); |
453 |
} |
454 |
if ($n < scalar(keys %algorithms)) { |
455 |
&perror("WARN", $file, -1, "no checksum records for all ". |
456 |
"supported algorithms (".join(" ",keys %algorithms).") for ". |
457 |
"$path."); |
458 |
} |
459 |
} |
460 |
return 1; |
461 |
} |
462 |
|
463 |
# |
464 |
# pkg-descr |
465 |
# |
466 |
sub checkdescr { |
467 |
my($file) = @_; |
468 |
my(%maxchars) = ($makevar{DESCR}, 80); |
469 |
my(%maxlines) = ($makevar{DESCR}, 24); |
470 |
my(%minlines) = ($makevar{DESCR}, 3); |
471 |
my(%toolongerrmsg) = ($makevar{DESCR}, |
472 |
"exceeds $maxlines{$makevar{DESCR}} ". |
473 |
"lines, make it shorter if possible."); |
474 |
my(%tooshorterrmsg) = ($makevar{DESCR}, |
475 |
"contains less than $minlines{$makevar{DESCR}} ". |
476 |
"lines, make it longer if possible."); |
477 |
my($longlines, $linecnt, $tmp) = (0, 0, ""); |
478 |
|
479 |
open(IN, "< $file") || return 0; |
480 |
while (<IN>) { |
481 |
$tmp .= $_; |
482 |
chomp || &perror("WARN", $file, -1, "lines should terminate with a ". |
483 |
"newline (i.e. '\\n')."); |
484 |
if (/ |
485 |
$/) { |
486 |
&perror("WARN", $file, -1, "lines should not contain carriage ". |
487 |
"returns. Strip all carriage returns (e.g. run dos2unix) ". |
488 |
"in $file."); |
489 |
} |
490 |
if (/^WWW:(\s+)(\S*)/) { |
491 |
my $wwwurl = $2; |
492 |
if ($1 ne ' ') { |
493 |
&perror("WARN", $file, -1, "use WWW: with a single space, ". |
494 |
"then $wwwurl"); |
495 |
} |
496 |
if ($wwwurl !~ m|^https?://|) { |
497 |
&perror("WARN", $file, -1, "WWW URL, $wwwurl should begin ". |
498 |
"with \"http://\" or \"https://\"."); |
499 |
} |
500 |
if ($wwwurl =~ m|^http://search.cpan.org/~|) { |
501 |
&perror("WARN", $file, -1, "consider changing WWW URL to ". |
502 |
"http://search.cpan.org/dist/$makevar{PORTNAME}/"); |
503 |
} |
504 |
} |
505 |
$linecnt++; |
506 |
$longlines++ if ($maxchars{$file} < length); |
507 |
} |
508 |
if ($linecnt > $maxlines{$file}) { |
509 |
&perror("WARN", $file, -1, "$toolongerrmsg{$file}". |
510 |
"(currently $linecnt lines)"); |
511 |
} elsif ($linecnt < $minlines{$file}) { |
512 |
&perror("WARN", $file, -1, "$tooshorterrmsg{$file}". |
513 |
"(currently $linecnt ".($linecnt > 1 ? "lines" : "line").")"); |
514 |
} else { |
515 |
print "OK: $file: has $linecnt lines.\n" if ($verbose); |
516 |
} |
517 |
if ($longlines > 0) { |
518 |
&perror("WARN", $file, -1, "includes lines that exceed $maxchars{$file} ". |
519 |
"characters."); |
520 |
} |
521 |
if ($tmp =~ /[\033\200-\377]/) { |
522 |
&perror("WARN", $file, -1, "includes iso-8859-1, or ". |
523 |
"other local characters. files should be in ". |
524 |
"plain 7-bit ASCII"); |
525 |
} |
526 |
if ($file =~ /\bpkg-descr/ && $tmp =~ m,https?://,) { |
527 |
my $has_url = 0; |
528 |
my $has_www = 0; |
529 |
my $cpan_url = 0; |
530 |
my $has_endslash = 0; |
531 |
foreach my $line (grep($_ =~ "https?://", split(/\n+/, $tmp))) { |
532 |
$has_url = 1; |
533 |
if ($line =~ m,WWW:[ \t]+https?://,) { |
534 |
$has_www = 1; |
535 |
if ($line =~ m,search.cpan.org,) { |
536 |
$cpan_url = 1; |
537 |
if ($line =~ m,/$,) { |
538 |
$has_endslash = 1; |
539 |
} |
540 |
} |
541 |
} |
542 |
} |
543 |
|
544 |
if (!$has_url) { |
545 |
&perror("WARN", $file, -1, "add \"WWW: URL:\" for this port if possible"); |
546 |
} |
547 |
|
548 |
if ($cpan_url && !$has_endslash) { |
549 |
&perror("WARN", $file, -1, "end WWW CPAN URL with a \"/\""); |
550 |
} |
551 |
|
552 |
if ($has_url && ! $has_www) { |
553 |
&perror("FATAL", $file, -1, "contains a URL but no \"WWW:\""); |
554 |
} |
555 |
} |
556 |
close(IN); |
557 |
} |
558 |
|
559 |
# |
560 |
# pkg-plist |
561 |
# |
562 |
sub checkplist { |
563 |
my($file) = @_; |
564 |
my($curdir) = ($localbase); |
565 |
my($rcsidseen) = (0); |
566 |
|
567 |
my $seen_special = 0; |
568 |
my $item_count = 0; |
569 |
my $owner_seen = 0; |
570 |
my $group_seen = 0; |
571 |
my $found_so = 0; |
572 |
|
573 |
# Variables that are allowed to be out-of-sync in the XXXDIR check. |
574 |
# E.g., %%PORTDOCS%%%%RUBY_MODDOCDIR%% will be OK because there is |
575 |
# no %%PORTRUBY_MODDOC%% substitution. |
576 |
my %check_xxxdir_ok = ( |
577 |
"DOCS" => "DOCS", |
578 |
"EXAMPLES" => "EXAMPLES", |
579 |
"DATA" => "DATA", |
580 |
"RUBY_DOC" => "DOCS", |
581 |
"RUBY_EXAMPLES" => "EXAMPLES", |
582 |
"RUBY_MODDOC" => "DOCS", |
583 |
"RUBY_MODEXAMPLES" => "EXAMPLES", |
584 |
); |
585 |
|
586 |
open(IN, "< $file") || return 0; |
587 |
while (<IN>) { |
588 |
$item_count++; |
589 |
if ($_ =~ /[ \t]+\n?$/) { |
590 |
&perror("WARN", $file, $., "whitespace before end ". |
591 |
"of line."); |
592 |
} |
593 |
|
594 |
# make it easier to handle. |
595 |
$_ =~ s/\s+$//; |
596 |
$_ =~ s/\n$//; |
597 |
|
598 |
if ($_ eq "") { |
599 |
&perror("WARN", $file, $., "empty line found in plist."); |
600 |
} |
601 |
|
602 |
# store possible OPTIONS knobs for OPTIONS_SUB |
603 |
if ($makevar{OPTIONS_SUB}) { |
604 |
while (/\%\%([^%]+)\%\%/g) { |
605 |
if ($1 =~ /PORTDOCS/) { |
606 |
push @popt, "DOCS"; |
607 |
} elsif ($1 =~ /PORTEXAMPLES/) { |
608 |
push @popt, "EXAMPLES"; |
609 |
} else { |
610 |
push @popt, $1; |
611 |
} |
612 |
} |
613 |
} |
614 |
|
615 |
if ($_ =~ /\.DS_Store/) { |
616 |
&perror("WARN", $file, $., ".DS_Store meta data files must not ". |
617 |
"be installed."); |
618 |
} |
619 |
|
620 |
if (m'lib/perl5/site_perl/mach/%%PERL_VER%%') { |
621 |
&perror("WARN", $file, $., "use \%\%SITE_ARCH\%\% ". |
622 |
"instead of lib/perl5/site_perl/mach/\%\%PERL_VER\%\%"); |
623 |
} elsif (m'lib/perl5/site_perl') { |
624 |
&perror("WARN", $file, $., "use \%\%SITE_PERL\%\% ". |
625 |
"instead of lib/perl5/site_perl."); |
626 |
} |
627 |
|
628 |
if (m'([\w\d]+-portbld-freebsd\d+\.\d+)') { |
629 |
&perror("WARN", $file, $., "possible direct use of the ". |
630 |
"CONFIGURE_TARGET value ($1). Consider using the plist ". |
631 |
"substitution %%CONFIGURE_TARGET%% instead."); |
632 |
} |
633 |
|
634 |
if (m'\@dirrm(try)?\s+libdata/pkgconfig') { |
635 |
&perror("FATAL", $file, $., "libdata/pkgconfig should not be ". |
636 |
"removed. It is listed in BSD.local.dist."); |
637 |
} |
638 |
|
639 |
if (m'\@dirrm(try)?\s') { |
640 |
&perror("WARN", $file, $., "\@dirrm[try] is deprecated. If you ". |
641 |
"require special directory handling, use \@dir instead and ". |
642 |
"consult the porter's handbook."); |
643 |
} |
644 |
|
645 |
if (m'\@cwd') { |
646 |
&perror("WARN", $file, $., "\@cwd is deprecated. Please use ". |
647 |
"absolute pathnames instead."); |
648 |
} |
649 |
|
650 |
if (m'\@stopdaemon\s') { |
651 |
&perror("WARN", $file, $., "\@stopdaemon is deprecated. The ". |
652 |
"pkg(8) has a generic mechanism to provide the same function, ". |
653 |
"see HANDLE_RC_SCRIPTS in pkg.conf(5)."); |
654 |
} |
655 |
|
656 |
if (m'^\@(un)?exec') { |
657 |
&perror("WARN", $file, $., "@[un]exec is deprecated in ". |
658 |
"favor of \@<pre|post>[un]exec as the latter specifies ". |
659 |
"the exact part of the pkg lifecycle the commands need ". |
660 |
"to run"); |
661 |
} |
662 |
|
663 |
$seen_special++ if /[\%\@]/; |
664 |
if ($_ =~ /^\@/) { |
665 |
if ($_ =~ /^\@(cwd|cd)[ \t]+(\S+)/) { |
666 |
$curdir = $2; |
667 |
} elsif ($_ =~ /^\@unexec[ \t]+rm[ \t]/) { |
668 |
if ($_ !~ /%[DB]/) { |
669 |
&perror("WARN", $file, $., "use \"%D\" or \"%B\" to ". |
670 |
"specify prefix."); |
671 |
} |
672 |
if ($_ !~ /true$/ && $_ !~ /rm -f/) { |
673 |
&perror("WARN", $file, $., "add \"2>&1 ". |
674 |
">/dev/null || true\" ". |
675 |
"to \"\@unexec rm\"."); |
676 |
} |
677 |
} elsif ($_ =~ /^\@unexec[ \t]+rmdir/) { |
678 |
if ($_ !~ /%[DB]/) { |
679 |
&perror("WARN", $file, $., "use \"%D\" or \"%B\" to ". |
680 |
"specify prefix."); |
681 |
} |
682 |
&perror("WARN", $file, $., "use \"\@dirrmtry\" ". |
683 |
"instead of \"\@unexec rmdir\"."); |
684 |
} elsif ($_ =~ /^\@unexec[ \t]+install-info[ \t]+--delete\s+(.+)\s+(.+)$/) { |
685 |
&perror("WARN", $file, $., "\@unexec install-info is deprecated in favor of adding info files into the Makefile using the INFO macro."); |
686 |
} elsif ($_ =~ /^\@(pre|post)?(exec|unexec|)/) { |
687 |
if (/ldconfig/) { |
688 |
&perror("WARN", $file, $., "possible ". |
689 |
"direct use of ldconfig ". |
690 |
"in PLIST found. use ". |
691 |
"USE_LDCONFIG instead."); |
692 |
} |
693 |
if (/scrollkeeper/) { |
694 |
&perror("WARN", $file, $., "possible ". |
695 |
"direct use of scrollkeeper commands ". |
696 |
"in PLIST found. Use ". |
697 |
"INSTALLS_OMF instead ". |
698 |
"(see http://www.FreeBSD.org/gnome/docs/porting.html ". |
699 |
"for more details)."); |
700 |
} |
701 |
} elsif ($_ =~ /^\@(comment)/) { |
702 |
$rcsidseen++ if (/\$$rcsidstr[:\$]/); |
703 |
} elsif ($_ =~ m!^\@(dirrm|dirrmtry)\s+/!) { |
704 |
&perror("WARN", $file, $., "Using \@$1 with absolute path ". |
705 |
"will not work as you expected in most cases. Use ". |
706 |
"\@dir... if you want to remove a directory such as ". |
707 |
"/var/\${PORTNAME}"); |
708 |
} elsif ($_ eq "\@cwd") { |
709 |
; # @cwd by itself means change directory back to the original |
710 |
# PREFIX. |
711 |
} elsif ($_ =~ /^\@\(/) { |
712 |
if ($_ !~ /^\@\([^,]*,[^,]*,[^\),]*(,[^\)]*)?\)/) { |
713 |
&perror("WARN", $file, $., "Invalid use of \@(...). ". |
714 |
"Arguments should be owner,group,perms[,fflags]"); |
715 |
} |
716 |
} elsif ($_ =~ /^\@sample\s+(.+)/) { |
717 |
my $sl = $.; |
718 |
my @sampleparts = split(/\s+/, $1); |
719 |
if (scalar @sampleparts == 1 && $sampleparts[0] !~ /\.sample$/) { |
720 |
&perror("WARN", $file, $sl, "\@sample directive references". |
721 |
" file that does not end in ``.sample''. Sample". |
722 |
" files must end in ``.sample''."); |
723 |
} |
724 |
} elsif ($_ =~ /^\@owner/) { |
725 |
if ($_ =~ /^\@owner\s+.+/) { |
726 |
if ($owner_seen > 0) { |
727 |
&perror("WARN", $file, $., "Nested setting of \@owner ". |
728 |
"found. Reset \@owner before setting it again."); |
729 |
} |
730 |
$owner_seen++; |
731 |
} else { |
732 |
if ($owner_seen == 0) { |
733 |
&perror("WARN", $file, $., "\@owner reset seen before ". |
734 |
"a new owner section was started."); |
735 |
} |
736 |
$owner_seen--; |
737 |
} |
738 |
} elsif ($_ =~ /^\@group/) { |
739 |
if ($_ =~ /^\@group\s+.+/) { |
740 |
if ($group_seen > 0) { |
741 |
&perror("WARN", $file, $., "Nested setting of \@group ". |
742 |
"found. Reset \@group before setting it again."); |
743 |
} |
744 |
$group_seen++; |
745 |
} else { |
746 |
if ($group_seen == 0) { |
747 |
&perror("WARN", $file, $., "\@group reset seen before ". |
748 |
"a new group section was started."); |
749 |
} |
750 |
$group_seen--; |
751 |
} |
752 |
} elsif ($_ =~ /^\@(dir|dirrm|dirrmtry|rmtry|option|stopdaemon|owner|group|mode|fc|fcfontsdir|fontsdir|info|shell)\b/) { |
753 |
; # no check made |
754 |
} else { |
755 |
&perror("WARN", $file, $., |
756 |
"unknown pkg-plist directive \"$_\""); |
757 |
} |
758 |
next; |
759 |
} |
760 |
|
761 |
if ($_ =~ /charset\.alias$/ || $_ =~ /locale\.alias$/) { |
762 |
&perror("WARN", $file, $., "installing charset.alias or locale.alias, ". |
763 |
"please add USES[+]=gettext and use libintl from devel/gettext ". |
764 |
"instead of from outdated bundled one if possible. ". |
765 |
"See http://www.freebsd.org/cgi/query-pr.cgi?pr=ports/71531 ". |
766 |
"for more details."); |
767 |
} |
768 |
|
769 |
if ($_ =~ /\%gconf.*\.xml/ || $_ =~ /gconf.*\.schemas?/) { |
770 |
&perror("FATAL", $file, $., "explicitly listing \%gconf key files ". |
771 |
"or GConf schema files in the plist is not supported. ". |
772 |
"Use GCONF_SCHEMAS in the Makefile instead. ". |
773 |
"See http://www.FreeBSD.org/gnome/docs/porting.html ". |
774 |
"for more details."); |
775 |
} |
776 |
|
777 |
if ($_ =~ m|lib/pkgconfig/[^\/]+.pc$|) { |
778 |
&perror("FATAL", $file, $., "installing pkg-config files into ". |
779 |
"lib/pkgconfig. All pkg-config files must be installed ". |
780 |
"into libdata/pkgconfig for them to be found by pkg-config."); |
781 |
} |
782 |
|
783 |
if ($_ =~ m|lib[^\/]+\.so(\.\d+)?$| && |
784 |
$makevar{USE_LDCONFIG} eq '') { |
785 |
&perror("WARN", $file, $., "installing shared libraries, ". |
786 |
"please define USE_LDCONFIG as appropriate"); |
787 |
} elsif ($_ =~ m|lib[^\/]+\.so(\.\d+)?$|) { |
788 |
$found_so++; |
789 |
} |
790 |
|
791 |
if ($_ =~ m|^share/icons/.*/| && |
792 |
$makevar{INSTALLS_ICONS} eq '' && |
793 |
needs_installs_icons()) { |
794 |
&perror("WARN", $file, $., "installing icons, ". |
795 |
"please define INSTALLS_ICONS as appropriate"); |
796 |
} |
797 |
|
798 |
if ($_ =~ m|\.omf$| && $makevar{INSTALLS_OMF} eq '') { |
799 |
&perror("WARN", $file, $., "installing OMF files, ". |
800 |
"please define INSTALLS_OMF (see the FreeBSD GNOME ". |
801 |
"porting guide at ". |
802 |
"http://www.FreeBSD.org/gnome/docs/porting.html ". |
803 |
"for more details)"); |
804 |
} |
805 |
|
806 |
if ($_ =~ m|^(%%([^%]+)%%)?.*\.mo$| && $makevar{USES} !~ /\bgettext\b/) { |
807 |
my $show_nls_warn = 1; |
808 |
if ($2) { |
809 |
my $mv = get_makevar($2."_USES"); |
810 |
if ($mv =~ /\bgettext\b/) { |
811 |
$show_nls_warn = 0; |
812 |
} |
813 |
} |
814 |
if ($show_nls_warn) { |
815 |
&perror("WARN", $file, $., "installing gettext translation files, ". |
816 |
"please define USES[+]=gettext as appropriate"); |
817 |
} |
818 |
} |
819 |
|
820 |
if ($_ =~ m|\.core$| && $_ !~ /^\@/) { |
821 |
&perror("WARN", $file, $., "this port installs a file which ends ". |
822 |
"in \".core\". This file may be deleted if ". |
823 |
"daily_clean_disks_enable=\"YES\" in /etc/periodic.conf. ". |
824 |
"If possible, install this file with a different name."); |
825 |
} |
826 |
|
827 |
if ($_ =~ m|/a\.out$| && $_ !~ /^\@/) { |
828 |
&perror("WARN", $file, $., "this port installs a file named ". |
829 |
"\"a.out\". This file may be deleted if ". |
830 |
"daily_clean_disks_enable=\"YES\" in /etc/periodic.conf. ". |
831 |
"If possible, install this file with a different name."); |
832 |
} |
833 |
|
834 |
if ($_ =~ /\.info$/) { |
835 |
&perror("WARN", $file, $., "enumerating info files in the plist is deprecated in favor of adding info files into the Makefile using the INFO macro."); |
836 |
} |
837 |
|
838 |
if ($_ =~ /\.info-\d+$/) { |
839 |
&perror("FATAL", $file, $., "numbered info files are obsolete and not portable; add info files using the INFO macro in the Makefile."); |
840 |
} |
841 |
|
842 |
if ($_ =~ /^(\%\%PORTDOCS\%\%)?share\/doc\//) { |
843 |
&perror("WARN", $file, $., "If and only if your port is ". |
844 |
"DOCSDIR-safe (that is, a user can override DOCSDIR ". |
845 |
"when building this port and the port will still work ". |
846 |
"correctly) consider using DOCSDIR macro; if you are ". |
847 |
"unsure if this port is DOCSDIR-safe, then ignore ". |
848 |
"this warning"); |
849 |
$sharedocused++; |
850 |
} elsif ($_ =~ /^(\%\%PORTDOCS\%\%)?\%\%DOCSDIR\%\%/) { |
851 |
$sharedocused++; |
852 |
} |
853 |
|
854 |
if ($_ =~ /^share\/examples\//) { |
855 |
&perror("WARN", $file, $., "If and only if your port is ". |
856 |
"EXAMPLESDIR-safe (that is, a user can override EXAMPLESDIR ". |
857 |
"when building this port and the port will still work ". |
858 |
"correctly) consider using EXAMPLESDIR macro; if you are ". |
859 |
"unsure if this port is EXAMPLESDIR-safe, then ignore this ". |
860 |
"warning"); |
861 |
} |
862 |
|
863 |
{ |
864 |
my $tmpportname = quotemeta($makevar{PORTNAME}); |
865 |
if ($_ =~ /^share\/$tmpportname\//) { |
866 |
&perror("WARN", $file, $., "If and only if your port is ". |
867 |
"DATADIR-safe (that is, a user can override DATADIR when ". |
868 |
"building this port and the port will still work ". |
869 |
"correctly) consider using DATADIR macro; if you are ". |
870 |
"unsure if this port is DATADIR-safe, then ignore this ". |
871 |
"warning"); |
872 |
} |
873 |
} |
874 |
|
875 |
if ($_ =~ m{^%%PORT(\w+)%%(.*?)%%(\w+)DIR%%(.*)$} and $1 ne $3 and |
876 |
defined($check_xxxdir_ok{$3})) { |
877 |
&perror("WARN", $file, $., "Do not mix %%PORT$1%% with %%$3DIR%%. ". |
878 |
"Use '%%PORT$check_xxxdir_ok{$3}%%$2%%$3DIR%%$4' instead and update Makefile ". |
879 |
"accordingly.") unless ($check_xxxdir_ok{$3} eq $1); |
880 |
} |
881 |
|
882 |
if ($_ =~ m#share/man/#) { |
883 |
&perror("FATAL", $file, $., "Man pages must be installed into ". |
884 |
"``man'' not ``share/man''."); |
885 |
} |
886 |
|
887 |
if ($_ =~ m#man/([^/]+/)?man[1-9ln]/([^\.]+\.[1-9ln])(\.gz)?$#) { |
888 |
if (!$3) { |
889 |
&perror("FATAL", $file, $., "Unpacked man file $2 listed. ". |
890 |
"Must be gzipped."); |
891 |
} |
892 |
} |
893 |
|
894 |
if ($curdir !~ m#^$localbase#) { |
895 |
&perror("WARN", $file, $., "installing to ". |
896 |
"directory $curdir discouraged. ". |
897 |
"could you please avoid it?"); |
898 |
} |
899 |
|
900 |
if ("$curdir/$_" =~ m#^$localbase/share/doc/#) { |
901 |
print "OK: $file [$.]: seen installation to share/doc. ". |
902 |
"($curdir/$_)\n" if ($verbose); |
903 |
$sharedocused++; |
904 |
} |
905 |
} |
906 |
|
907 |
if ($owner_seen > 0) { |
908 |
&perror("WARN", $file, -1, "A \@owner section was started but never ". |
909 |
"reset. USe \@owner without any arguments to reset the owner"); |
910 |
} |
911 |
|
912 |
if ($group_seen > 0) { |
913 |
&perror("WARN", $file, -1, "A \@group section was started but never ". |
914 |
"reset. Use \@group without any arguments to reset the group"); |
915 |
} |
916 |
|
917 |
if (!$seen_special && $item_count < $numpitems) { |
918 |
&perror("WARN", $file, -1, "There are only $item_count items in the plist. Consider using PLIST_FILES instead of pkg-plist when installing less than $numpitems items."); |
919 |
} |
920 |
|
921 |
if ($makevar{USE_LDCONFIG} ne '' && !$found_so) { |
922 |
&perror("WARN", $file, -1, "You have defined USE_LDCONFIG, but this ". |
923 |
"port does not install any shared objects."); |
924 |
} |
925 |
|
926 |
close(IN); |
927 |
1; |
928 |
} |
929 |
# |
930 |
# ${PORTSDIR}/MOVED, UIDs, GIDs files |
931 |
# |
932 |
sub checkmfile { |
933 |
my ($file) = @_; |
934 |
my $line = 0; |
935 |
my $format; |
936 |
my @entries; |
937 |
my @sorted; |
938 |
my $dosort; |
939 |
|
940 |
if ($file =~ m/MOVED$/) { |
941 |
$format = '^[^|]*\|[^|]*\|[^|]*\|[^|]*$'; |
942 |
$dosort = 0; |
943 |
} elsif ($file =~ m/UIDs$/) { |
944 |
$format = '^[^:]+:\*:[0-9]+:[0-9]+:[^:]*:0:0:[^:]+:[^:]+:[^:]+$'; |
945 |
$dosort = 1; |
946 |
} elsif ($file =~ m/GIDs$/) { |
947 |
$format = '^[^:]+:\*:[0-9]+:[^:]*$'; |
948 |
$dosort = 1; |
949 |
} else { |
950 |
&perror("FATAL", $file, -1, "Internal error. ". |
951 |
"Invalid name for mfiles."); |
952 |
} |
953 |
|
954 |
open(IN, "<$file") || return 0; |
955 |
while (<IN>) { |
956 |
chomp; |
957 |
$line++; |
958 |
next if (m,^\s*#,); |
959 |
|
960 |
if (!m,${format},) { |
961 |
&perror("FATAL", $file, -1, |
962 |
"malformed line at ". |
963 |
"${line}.\n => $_"); |
964 |
} else { |
965 |
push @entries, "$line:$_"; |
966 |
next; |
967 |
} |
968 |
} |
969 |
if ($dosort) { |
970 |
my $errline; |
971 |
@sorted = sort {(split /:/, $a)[3] <=> (split /:/, $b)[3] } @entries; |
972 |
|
973 |
for (my $n = 0; $n < @entries; $n++) { |
974 |
if (!defined($sorted[$n]) or |
975 |
$entries[$n] ne $sorted[$n]) { |
976 |
($line, $errline) = ($entries[$n] =~ m/([0-9]+):(.*)/); |
977 |
&perror("WARN", $file, -1, |
978 |
"malformed sorting order at " . |
979 |
"${line}.\n => $errline"); |
980 |
} |
981 |
} |
982 |
} |
983 |
close(IN); |
984 |
} |
985 |
# |
986 |
# misc files |
987 |
# |
988 |
sub checkpathname { |
989 |
my($file) = @_; |
990 |
my($whole); |
991 |
|
992 |
open(IN, "< $file") || return 0; |
993 |
$whole = ''; |
994 |
while (<IN>) { |
995 |
$whole .= $_; |
996 |
} |
997 |
&abspathname($whole, $file); |
998 |
close(IN); |
999 |
} |
1000 |
|
1001 |
sub checklastline { |
1002 |
my($file) = @_; |
1003 |
my($whole); |
1004 |
|
1005 |
open(IN, "< $file") || return 0; |
1006 |
$whole = ''; |
1007 |
while (<IN>) { |
1008 |
$whole .= $_; |
1009 |
} |
1010 |
if ($whole !~ /\n$/) { |
1011 |
&perror("FATAL", $file, -1, "the last line has to be ". |
1012 |
"terminated by \\n."); |
1013 |
} |
1014 |
if ($whole =~ /\n([ \t]*\n)+$/) { |
1015 |
&perror("WARN", $file, -1, "seems to have unnecessary blank lines ". |
1016 |
"at the last part."); |
1017 |
} |
1018 |
|
1019 |
close(IN); |
1020 |
} |
1021 |
|
1022 |
sub checkpatch { |
1023 |
my($file) = @_; |
1024 |
my($whole); |
1025 |
|
1026 |
if (-z "$file") { |
1027 |
&perror("FATAL", $file, -1, "has no content. should be removed ". |
1028 |
"from repository."); |
1029 |
return; |
1030 |
} |
1031 |
|
1032 |
my $bfile = basename($file); |
1033 |
|
1034 |
if (length $bfile > 100) { |
1035 |
&perror("FATAL", $file, -1, "make sure patch file names contain no ". |
1036 |
"more than 100 characters."); |
1037 |
} |
1038 |
|
1039 |
open(IN, "< $file") || return 0; |
1040 |
$whole = ''; |
1041 |
my $checked_header = 0; |
1042 |
while (<IN>) { |
1043 |
$whole .= $_; |
1044 |
if (/^--- / && !$checked_header) { |
1045 |
$checked_header = 1; |
1046 |
if ($_ !~ /UTC\s*$/) { |
1047 |
&perror("WARN", $file, -1, "patch was not generated using ". |
1048 |
"``make makepatch''. It is recommended to use ". |
1049 |
"``make makepatch'' when you need to [re-]generate a ". |
1050 |
"patch to ensure proper patch format."); |
1051 |
} |
1052 |
} |
1053 |
} |
1054 |
|
1055 |
if ($committer && $whole =~ /\wjavavm\w/) { |
1056 |
my $lineno = &linenumber($`); |
1057 |
&perror("WARN", $file, $lineno, "since javavmwrapper 2.0, the ". |
1058 |
"``javavm'' command to invoke a JVM is deprecated. Use ". |
1059 |
"``java'' instead"); |
1060 |
} |
1061 |
|
1062 |
if ($whole =~ / |
1063 |
/) { |
1064 |
my $lineno = &linenumber($`); |
1065 |
&perror("WARN", $file, $lineno, "patch contains ^M characters. ". |
1066 |
"Consider defining USES=dos2unix to remove DOS line endings ". |
1067 |
"from source files."); |
1068 |
} |
1069 |
|
1070 |
if ($whole !~ /\n$/s) { |
1071 |
&perror("FATAL", $file, -1, "patch does not end with a newline, and the commit check ". |
1072 |
"hook will fail."); |
1073 |
} |
1074 |
|
1075 |
close(IN); |
1076 |
} |
1077 |
|
1078 |
sub check_depends_syntax { |
1079 |
my $tmp = shift; |
1080 |
my $file = shift; |
1081 |
my (%seen_depends, $j); |
1082 |
|
1083 |
$ENV{'PORTSDIR'} //= $portsdir; |
1084 |
|
1085 |
foreach my $i (grep(/^(PATCH_|EXTRACT_|LIB_|BUILD_|RUN_|TEST_|FETCH_)*DEPENDS[?+]?=/, split(/\n/, $tmp))) { |
1086 |
$i =~ s/^((PATCH_|EXTRACT_|LIB_|BUILD_|RUN_|TEST_|FETCH_)*DEPENDS)[?+]?=[ \t]*//; |
1087 |
$j = $1; |
1088 |
$seen_depends{$j}++; |
1089 |
if ($j ne 'DEPENDS' && |
1090 |
$i =~ /^\$\{([A-Z_]+DEPENDS)}\s*$/ && |
1091 |
$seen_depends{$1} && |
1092 |
$j ne $1) |
1093 |
{ |
1094 |
print "OK: $j refers to $1, skipping checks.\n" |
1095 |
if ($verbose); |
1096 |
next; |
1097 |
} |
1098 |
print "OK: checking ports listed in $j.\n" if ($verbose); |
1099 |
my @ks = split(/\s+/, $i); |
1100 |
while (@ks) { |
1101 |
my $k = shift @ks; |
1102 |
if ($k =~ /^#/) { |
1103 |
last; |
1104 |
} |
1105 |
my $ok = $k; |
1106 |
if ($k =~ /^\$\{(\w+)\}$/) { |
1107 |
$k = get_makevar($1); |
1108 |
push @ks, split(/\s+/, $k); |
1109 |
next; |
1110 |
} |
1111 |
if ($k eq '') { |
1112 |
next; |
1113 |
} |
1114 |
my @l = split(':', $k); |
1115 |
|
1116 |
print "OK: checking dependency value for $j.\n" |
1117 |
if ($verbose); |
1118 |
if ($ok =~ /\$\{((PATCH_|EXTRACT_|LIB_|BUILD_|RUN_|TEST_|FETCH_)*DEPENDS)}/) { |
1119 |
&perror("WARN", $file, -1, "do not set $j to $ok. ". |
1120 |
"Instead, explicity list out required $j dependencies."); |
1121 |
} |
1122 |
|
1123 |
if (($j ne 'DEPENDS' |
1124 |
&& scalar(@l) != 2 && scalar(@l) != 3)) { |
1125 |
&perror("WARN", $file, -1, "wrong dependency value ". |
1126 |
"for $j. $j requires ". |
1127 |
"2 or 3 ". |
1128 |
"colon-separated tuples."); |
1129 |
next; |
1130 |
} |
1131 |
my %m = (); |
1132 |
$m{'dep'} = $l[0]; |
1133 |
my ($di, $fl) = split(/\@/, $l[1]); |
1134 |
$m{'dir'} = $di; |
1135 |
$m{'fla'} = $fl // ''; |
1136 |
$m{'tgt'} = $l[2] // ''; |
1137 |
my %depmvars = (); |
1138 |
foreach my $dv ($m{'dep'}, $m{'dir'}, $m{'tgt'}) { |
1139 |
foreach my $mv ($dv =~ /\$\{([^}]+)\}/g) { |
1140 |
if (defined($depmvars{$mv})) { |
1141 |
next; |
1142 |
} |
1143 |
if (defined($makevar{$mv})) { |
1144 |
$depmvars{$mv} = $makevar{$mv}; |
1145 |
} else { |
1146 |
$depmvars{$mv} = &get_makevar($mv); |
1147 |
} |
1148 |
} |
1149 |
} |
1150 |
|
1151 |
# check Python flavor |
1152 |
my $bdir = basename($m{'dir'}); |
1153 |
if ($bdir =~ /^py-/) { |
1154 |
if ($m{'fla'} ne '${PY_FLAVOR}') { |
1155 |
&perror("WARN", $file, -1, "you may want directory for ". |
1156 |
"dependency $m{'dep'} to be $m{'dir'}\@\${PY_FLAVOR}"); |
1157 |
} |
1158 |
} |
1159 |
|
1160 |
# check JAVALIBDIR |
1161 |
if ($m{'dep'} =~ m|share/java/classes|) { |
1162 |
&perror("FATAL", $file, -1, "you should use \${JAVALIBDIR} ". |
1163 |
"in BUILD_DEPENDS/RUN_DEPENDS to define ". |
1164 |
"dependencies on JAR files installed in ". |
1165 |
"\${JAVAJARDIR}"); |
1166 |
} |
1167 |
|
1168 |
foreach my $dv ($m{'dep'}, $m{'dir'}, $m{'tgt'}) { |
1169 |
foreach my $dmv (keys %depmvars) { |
1170 |
$dv =~ s/\$\{$dmv\}/$depmvars{$dmv}/g; |
1171 |
} |
1172 |
} |
1173 |
|
1174 |
print "OK: dep=\"$m{'dep'}\", ". |
1175 |
"dir=\"$m{'dir'}\", tgt=\"$m{'tgt'}\"\n" |
1176 |
if ($verbose); |
1177 |
|
1178 |
# check USES=perl5 |
1179 |
if ($m{'dep'} =~ /^perl5(\.\d+)?$/) { |
1180 |
&perror("WARN", $file, -1, "dependency to perl5 ". |
1181 |
"listed in $j. consider using ". |
1182 |
"USES[+]=perl5."); |
1183 |
} |
1184 |
|
1185 |
# Check for ${SITE_PERL} in depends |
1186 |
if ($m{'dep'} =~ m|^(\$\{SITE_PERL}/.*)$|) { |
1187 |
&perror("WARN", $file, -1, "dependency to $1 ". |
1188 |
"listed in $j. consider using p5-Example-Package-Name>=0. See ". |
1189 |
"http://www.freebsd.org/doc/en/books/porters-handbook/using-perl.html". |
1190 |
" for more details."); |
1191 |
} |
1192 |
|
1193 |
# check USES=iconv |
1194 |
if ($m{'dep'} =~ /^(iconv\.\d+)$/) { |
1195 |
&perror("WARN", $file, -1, "dependency to $1 ". |
1196 |
"listed in $j. consider using ". |
1197 |
"USES[+]=iconv."); |
1198 |
} |
1199 |
|
1200 |
# check USES=gettext |
1201 |
if ($m{'dep'} =~ /^(intl\.\d+)$/) { |
1202 |
&perror("WARN", $file, -1, "dependency to $1 ". |
1203 |
"listed in $j. consider using ". |
1204 |
"USES[+]=gettext."); |
1205 |
} |
1206 |
|
1207 |
# check USES=gmake |
1208 |
if ($m{'dep'} =~ /^(gmake|\$\{GMAKE})$/) { |
1209 |
&perror("WARN", $file, -1, "dependency to $1 ". |
1210 |
"listed in $j. consider using ". |
1211 |
"USES[+]=gmake."); |
1212 |
} |
1213 |
|
1214 |
my %udeps = ( |
1215 |
'bison' => 'bison', |
1216 |
'fmake' => 'fmake', |
1217 |
); |
1218 |
foreach my $udep (keys %udeps) { |
1219 |
if ($m{'dep'} =~ /^$udep/) { |
1220 |
&perror("WARN", $file, -1, "dependency to $udep ". |
1221 |
"listed in $j. consider using ". |
1222 |
"USES[+]=$udeps{$udep}."); |
1223 |
} |
1224 |
} |
1225 |
|
1226 |
# check USE_QT |
1227 |
if ($m{'dep'} =~ /^(qt\d)+$/) { |
1228 |
&perror("WARN", $file, -1, "dependency to $1 ". |
1229 |
"listed in $j. consider using ". |
1230 |
"USE_QT."); |
1231 |
} |
1232 |
|
1233 |
# check LIBLTDL |
1234 |
if ($m{'dep'} =~ /^(ltdl\.\d)+$/) { |
1235 |
&perror("WARN", $file, -1, "dependency to $1 ". |
1236 |
"listed in $j. consider using ". |
1237 |
"USE_LIBLTDL."); |
1238 |
} |
1239 |
|
1240 |
# check GHOSTSCRIPT |
1241 |
if ($m{'dep'} eq "gs") { |
1242 |
&perror("WARN", $file, -1, "dependency to gs ". |
1243 |
"listed in $j. consider using ". |
1244 |
"USE_GHOSTSCRIPT(_BUILD|_RUN)."); |
1245 |
} |
1246 |
|
1247 |
|
1248 |
# check for PREFIX |
1249 |
if ($m{'dep'} =~ /\$\{PREFIX}/) { |
1250 |
&perror("FATAL", $file, -1, "\${PREFIX} must not be ". |
1251 |
"contained in *_DEPENDS. ". |
1252 |
"use \${LOCALBASE} instead."); |
1253 |
} |
1254 |
|
1255 |
# Check for direct dependency on apache. |
1256 |
if ($m{'dep'} =~ /\/www\/apache\d*\//) { |
1257 |
&perror("FATAL", $file, -1, "do not depend on any apache ". |
1258 |
"port in *_DEPENDS directly. ". |
1259 |
"Instead use USE_APACHE=VERSION, where VERSION can be ". |
1260 |
"found in \${PORTSDIR}/Mk/bsd.apache.mk."); |
1261 |
} |
1262 |
|
1263 |
# Check for over-specific shared library dependencies |
1264 |
if ($j eq 'LIB_DEPENDS' && $m{'dep'} =~ m/(\.\d+$)/) { |
1265 |
&perror("WARN", $file, -1, "$j don't specify the " . |
1266 |
"ABI version number $1 in $m{'dep'} unless it is " . |
1267 |
"really necessary."); |
1268 |
} |
1269 |
|
1270 |
# Check for old-style LIB_DEPENDS |
1271 |
if ($j eq 'LIB_DEPENDS' && $m{'dep'} !~ m/^lib.*\.so$/) { |
1272 |
&perror("WARN", $file, -1, "$j the new format is ". |
1273 |
"libFOO.so (e.g., lib$m{'dep'}.so)."); |
1274 |
} |
1275 |
|
1276 |
# Check port dir existence |
1277 |
$k = $ENV{'PORTSDIR'}.'/'.$m{'dir'}; |
1278 |
if (! -d $k) { |
1279 |
&perror("WARN", $file, -1, "no port directory $k ". |
1280 |
"found, even though it is ". |
1281 |
"listed in $j."); |
1282 |
} else { |
1283 |
print "OK: port directory $k found.\n" |
1284 |
if ($verbose); |
1285 |
} |
1286 |
|
1287 |
# Check for relative path |
1288 |
if ($k =~ /\/\.\.\//) { |
1289 |
&perror("FATAL", $file, -1, "use absolute path". |
1290 |
"instead of $k in *_DEPENDS."); |
1291 |
} else { |
1292 |
print "OK: path for port directory $k is absolute.\n" |
1293 |
if ($verbose); |
1294 |
} |
1295 |
} |
1296 |
} |
1297 |
} |
1298 |
|
1299 |
# |
1300 |
# Makefile |
1301 |
# |
1302 |
sub checkmakefile { |
1303 |
my($file) = @_; |
1304 |
my($rawwhole, $whole, $idx, @sections); |
1305 |
my($i, $j, $k, $l); |
1306 |
my @cat = (); |
1307 |
my $has_lang_cat = 0; |
1308 |
my $port_lang = ''; |
1309 |
my $tmp; |
1310 |
my $bogusdistfiles = 0; |
1311 |
my @varnames = (); |
1312 |
my($portname, $portversion, $distfiles, $distversionprefix, $distversion, $distversionsuffix, $distname, $extractsufx) = ('') x 8; |
1313 |
my $masterport = 0; |
1314 |
my $slaveport = 0; |
1315 |
my $use_gnome_hack = 0; |
1316 |
my $use_java = 0; |
1317 |
my $use_ant = 0; |
1318 |
my($realwrksrc, $wrksrc, $nowrksubdir) = ('', '', ''); |
1319 |
my(@mman, @pman); |
1320 |
my(@aopt, @mopt, @opt); |
1321 |
my($pkg_version, $versiondir, $versionfile) = ('', '', ''); |
1322 |
my $useindex = 0; |
1323 |
my %deprecated = (); |
1324 |
my @deplist = (); |
1325 |
my %autocmdnames = (); |
1326 |
my $pre_mk_line = 0; |
1327 |
my $options_mk_line = 0; |
1328 |
my $docsused = 0; |
1329 |
my $optused = 0; |
1330 |
my $desktop_entries = ''; |
1331 |
|
1332 |
my $masterdir = $makevar{MASTERDIR}; |
1333 |
if ($masterdir ne '' && $masterdir ne $makevar{'.CURDIR'}) { |
1334 |
$slaveport = 1; |
1335 |
} |
1336 |
|
1337 |
open(IN, "< $file") || return 0; |
1338 |
$rawwhole = ''; |
1339 |
$tmp = 0; |
1340 |
while (<IN>) { |
1341 |
if ($_ =~ /[ \t]+\n?$/) { |
1342 |
&perror("WARN", $file, $., "whitespace before ". |
1343 |
"end of line."); |
1344 |
} |
1345 |
if ($_ =~ /^ /) { # 8 spaces here! |
1346 |
&perror("WARN", $file, $., "use tab (not space) to make ". |
1347 |
"indentation"); |
1348 |
} |
1349 |
if ($usetabs) { |
1350 |
if (m/^[A-Za-z0-9_-]+.?=\t*? \t*?/) { |
1351 |
if (m/[?+]=/) { |
1352 |
&perror("WARN", $file, $., "use a tab (not space) after a ". |
1353 |
"variable name"); |
1354 |
} else { |
1355 |
&perror("FATAL", $file, $., "use a tab (not space) after a ". |
1356 |
"variable name"); |
1357 |
} |
1358 |
} |
1359 |
} |
1360 |
$rawwhole .= $_; |
1361 |
} |
1362 |
close(IN); |
1363 |
|
1364 |
# |
1365 |
# whole file: blank lines. |
1366 |
# |
1367 |
$whole = "\n" . $rawwhole; |
1368 |
study $whole; |
1369 |
print "OK: checking contiguous blank lines in $file.\n" |
1370 |
if ($verbose); |
1371 |
$i = "\n" x ($contblank + 2); |
1372 |
if ($whole =~ /$i/) { |
1373 |
my $lineno = &linenumber($`); |
1374 |
&perror("FATAL", $file, $lineno, "contiguous blank lines ". |
1375 |
"(> $contblank lines) found."); |
1376 |
} |
1377 |
|
1378 |
# |
1379 |
# whole file: header |
1380 |
# |
1381 |
my @lines = split("\n", $whole); |
1382 |
print "OK: checking header in $file.\n" if ($verbose); |
1383 |
if ($lines[1] =~ /^# (?:New )?[Pp]orts collection [mM]akefile/) { |
1384 |
&perror("FATAL", $file, 1, "old style headers found."); |
1385 |
} elsif ($lines[1] =~ /^# Created by: \S/) { |
1386 |
if ($lines[2] !~ /^# \$$rcsidstr[:\$]/) { |
1387 |
&perror("FATAL", $file, 2, "header should be ". |
1388 |
"followed by \$$rcsidstr\$."); |
1389 |
} elsif ($lines[3] !~ /^$/) { |
1390 |
#&perror("FATAL", $file, 3, "do not add extra ". |
1391 |
# "empty comments after header."); |
1392 |
} |
1393 |
# special case for $rcsidsrt\nMCom: |
1394 |
} elsif ($lines[1] =~ /^# \$$rcsidstr[:\$]/ and $lines[2] =~ /^#\s+\$MCom[:\$]/ and $lines[3] =~ /^$/) { |
1395 |
# DO NOTHING |
1396 |
} elsif ($lines[1] !~ /^# \$$rcsidstr[:\$]/ or $lines[2] !~ /^$/) { |
1397 |
&perror("FATAL", $file, 1, "incorrect header; ". |
1398 |
"simply use \$$rcsidstr\$."); |
1399 |
} |
1400 |
|
1401 |
# |
1402 |
# whole file: $(VARIABLE) |
1403 |
# |
1404 |
if ($parenwarn) { |
1405 |
print "OK: checking for \$(VARIABLE).\n" if ($verbose); |
1406 |
if ($whole =~ /[^\$]\$\([\w\d]+\)/) { |
1407 |
my $lineno = &linenumber($`); |
1408 |
&perror("WARN", $file, $lineno, "use \${VARIABLE}, instead of ". |
1409 |
"\$(VARIABLE)."); |
1410 |
} |
1411 |
} |
1412 |
|
1413 |
# |
1414 |
# whole file: empty(${VARIABLE}) |
1415 |
# |
1416 |
if ($parenwarn) { |
1417 |
print "OK: checking for empty(\${VARIABLE}).\n" if ($verbose); |
1418 |
if ($whole =~ /empty\(\$\{[\w\d]+/) { |
1419 |
my $lineno = &linenumber($`); |
1420 |
&perror("WARN", $file, $lineno, "use empty(VARIABLE), instead of ". |
1421 |
"empty(\${VARIABLE})."); |
1422 |
} |
1423 |
} |
1424 |
|
1425 |
# |
1426 |
# whole file: use of != |
1427 |
# |
1428 |
print "OK: checking for use of !=.\n" if ($verbose); |
1429 |
if ($whole =~ /^[\w\d_]+\!=/m) { |
1430 |
my $lineno = &linenumber($`); |
1431 |
&perror("WARN", $file, $lineno, "use of != in assignments is almost ". |
1432 |
"never a good thing to do. Try to avoid using them. See ". |
1433 |
"http://lists.freebsd.org/pipermail/freebsd-ports/2008-July/049777.html ". |
1434 |
"for some helpful hints on what to do instead."); |
1435 |
} |
1436 |
|
1437 |
# |
1438 |
# whole file: use of .elseif |
1439 |
# |
1440 |
print "OK: checking for use of .elseif.\n" if ($verbose); |
1441 |
if ($whole =~ /^\.\s*else\s*if/m) { |
1442 |
my $lineno = &linenumber($`); |
1443 |
&perror("FATAL", $file, $lineno, "use of .elseif (or .else if) is not ". |
1444 |
"supported in all versions of BSD. Use .elif instead."); |
1445 |
} |
1446 |
|
1447 |
# |
1448 |
# whole file: use of @${INSTALL_foo} |
1449 |
# |
1450 |
print "OK: checking for use of muted INSTALL_ commands.\n" if ($verbose); |
1451 |
if ($whole =~ /^\s+\@\$\{INSTALL_/m) { |
1452 |
my $lineno = &linenumber($`); |
1453 |
&perror("WARN", $file, $lineno, "do not use muted INSTALL_foo ". |
1454 |
"commands (i.e., those that start with '\@'). These should be ". |
1455 |
"printed."); |
1456 |
} |
1457 |
|
1458 |
# |
1459 |
# checking for use of ${ENV} |
1460 |
# |
1461 |
print "OK: checking for use of \${ENV} instead of \${SETENV}.\n" if ($verbose); |
1462 |
if ($whole =~ /\$\{ENV}/m) { |
1463 |
my $lineno = &linenumber($`); |
1464 |
&perror("WARN", $file, $lineno, "most uses of \${ENV} should really ". |
1465 |
"be \${SETENV} to avoid strange behaviors in sh(1)."); |
1466 |
} |
1467 |
|
1468 |
# |
1469 |
# whole file: use of IGNOREFILES |
1470 |
# |
1471 |
print "OK: checking for use of IGNOREFILES.\n" if ($verbose); |
1472 |
if ($whole =~ /\nIGNOREFILES.?=/m) { |
1473 |
my $lineno = &linenumber($`); |
1474 |
&perror("FATAL", $file, $lineno, "IGNOREFILES considered unsafe and ". |
1475 |
"not supported anymore."); |
1476 |
} |
1477 |
|
1478 |
# |
1479 |
# whole file: use of PLIST_DIRSTRY |
1480 |
# |
1481 |
print "OK: checking for use of PLIST_DIRSTRY.\n" if ($verbose); |
1482 |
if ($whole =~ /\nPLIST_DIRSTRY.?=/m) { |
1483 |
my $lineno = &linenumber($`); |
1484 |
&perror("WARN", $file, $lineno, "PLIST_DIRSTRY is deprecated. Please ". |
1485 |
"use PLIST_DIRS instead."); |
1486 |
} |
1487 |
|
1488 |
# |
1489 |
# whole file: PLIST_FILES and PLIST_DIRS |
1490 |
# |
1491 |
print "OK: checking PLIST_FILES and PLIST_DIRS.\n" if ($verbose); |
1492 |
if ($whole =~ /\nPLIST_FILES.?=/ || $whole =~ /\nPLIST_DIRS.?=/) { |
1493 |
if (-f 'pkg-plist') { |
1494 |
my $lineno = &linenumber($`); |
1495 |
&perror("WARN", $file, $lineno, "You may remove pkg-plist ". |
1496 |
"if you use PLIST_FILES and/or PLIST_DIRS."); |
1497 |
} |
1498 |
my @plist_files = split(/\s+/, $makevar{PLIST_FILES}); |
1499 |
foreach my $plist_file (@plist_files) { |
1500 |
if ($plist_file =~ m|lib[^\/]+\.so(\.\d+)?$| && |
1501 |
$makevar{USE_LDCONFIG} eq '') { |
1502 |
&perror("WARN", "", -1, "PLIST_FILES: installing shared libraries, ". |
1503 |
"please define USE_LDCONFIG as appropriate"); |
1504 |
} |
1505 |
if ($plist_file =~ m|\.omf$| && $makevar{INSTALLS_OMF} eq '') { |
1506 |
&perror("WARN", "", -1, "PLIST_FILES: installing OMF files, ". |
1507 |
"please define INSTALLS_OMF (see the FreeBSD GNOME ". |
1508 |
"porting guide at ". |
1509 |
"http://www.FreeBSD.org/gnome/docs/porting.html ". |
1510 |
"for more details)"); |
1511 |
} |
1512 |
if ($plist_file =~ m|\.core$| && $plist_file !~ /^\@/) { |
1513 |
&perror("WARN", "", -1, "PLIST_FILES: this port installs a file which ". |
1514 |
"ends in \".core\". This file may be deleted if ". |
1515 |
"daily_clean_disks_enable=\"YES\" in /etc/periodic.conf. ". |
1516 |
"If possible, install this file with a different name."); |
1517 |
} |
1518 |
if ($plist_file =~ m|^share/icons/.*/| && |
1519 |
$makevar{INSTALLS_ICONS} eq '' && |
1520 |
needs_installs_icons()) { |
1521 |
&perror("WARN", "", -1, "PLIST_FILES: installing icons, ". |
1522 |
"please define INSTALLS_ICONS as appropriate"); |
1523 |
} |
1524 |
if ($plist_file =~ /%%[\w_\d]+%%/) { |
1525 |
&perror("FATAL", "", -1, "PLIST_FILES: files cannot contain ". |
1526 |
"%%FOO%% variables. Use make variables and logic instead"); |
1527 |
} |
1528 |
|
1529 |
} |
1530 |
} |
1531 |
|
1532 |
# |
1533 |
# whole file: USE_* and others variables used too late |
1534 |
# |
1535 |
my @options_early = qw( |
1536 |
OPTIONS_DEFAULT |
1537 |
OPTIONS_DEFINE |
1538 |
OPTIONS_EXCLUDE |
1539 |
OPTIONS_GROUP.*? |
1540 |
OPTIONS_MULTI.*? |
1541 |
OPTIONS_RADIO.*? |
1542 |
OPTIONS_SINGLE.*? |
1543 |
); |
1544 |
|
1545 |
pos($whole) = 0; |
1546 |
if ($whole =~ /^\.include\s+<bsd\.port\.pre\.mk>$/gm) { |
1547 |
# Remember position |
1548 |
$pre_mk_line = &linenumber($`) + 1; |
1549 |
print "OK: checking for USE_* used too late.\n" if ($verbose); |
1550 |
my @use_early = qw( |
1551 |
BZIP2 |
1552 |
GNUSTEP |
1553 |
IMAKE |
1554 |
KDE(?:BASE|LIBS)_VER |
1555 |
(?:LIB)?RUBY |
1556 |
LINUX_PREFIX |
1557 |
OPENSSL |
1558 |
PYTHON |
1559 |
QT2? |
1560 |
QT_VER |
1561 |
X_PREFIX |
1562 |
ZIP |
1563 |
); |
1564 |
|
1565 |
my @other_early = qw( |
1566 |
EMACS_PORT_NAME |
1567 |
); |
1568 |
|
1569 |
my $earlypattern = join('|', 'USE_(?:'.join('|', @use_early).')', |
1570 |
@other_early, @options_early); |
1571 |
|
1572 |
while ($whole =~ /^($earlypattern)[+?:!]?=/gmo) { |
1573 |
my $lineno = &linenumber($`); |
1574 |
&perror("FATAL", $file, $lineno, "$1 is set after ". |
1575 |
"including bsd.port.pre.mk."); |
1576 |
} |
1577 |
} |
1578 |
|
1579 |
# |
1580 |
# whole file: check OPTIONS |
1581 |
# |
1582 |
print "OK: checking OPTIONS.\n" if ($verbose); |
1583 |
pos($whole) = 0; |
1584 |
if ($whole =~ /^\.include\s+<bsd\.port\.options\.mk>$/gm) { |
1585 |
# Remember position |
1586 |
$options_mk_line = &linenumber($`) + 1; |
1587 |
} |
1588 |
|
1589 |
pos($whole) = 0; |
1590 |
if ($whole =~ /^\.include\s+<bsd\.port\.options\.mk>$/gm) { |
1591 |
my $earlypattern = join('|', @options_early); |
1592 |
while ($whole =~ /^($earlypattern)[+?]?=/gmo) { |
1593 |
my $lineno = &linenumber($`); |
1594 |
&perror("FATAL", $file, $lineno, "$1 is set after ". |
1595 |
"including bsd.port.options.mk."); |
1596 |
} |
1597 |
} |
1598 |
|
1599 |
pos($whole) = 0; |
1600 |
foreach my $i ("OPTIONS_RADIO","OPTIONS_SINGLE", |
1601 |
"OPTIONS_MULTI","OPTIONS_GROUP") { |
1602 |
foreach my $j (split(/\s+/, $makevar{$i})) { |
1603 |
if ($j) { |
1604 |
my @ocount = split(/\s+/, get_makevar("${i}_${j}")); |
1605 |
if (!scalar(@ocount)) { |
1606 |
&perror("FATAL", $file, -1, |
1607 |
"Description for ${i}_${j} does not exist"); |
1608 |
} else { |
1609 |
push @aopt, @ocount; |
1610 |
} |
1611 |
} |
1612 |
} |
1613 |
} |
1614 |
|
1615 |
@opt = split(/\s+/, $makevar{OPTIONS_DEFINE}); |
1616 |
pos($whole) = 0; |
1617 |
while ($whole =~ /PORT_OPTIONS:M(\w+)/mg) { |
1618 |
push @mopt, $1; |
1619 |
my $lineno = &linenumber($`) + 1; |
1620 |
&perror("FATAL", $file, $lineno, "PORT_OPTIONS:M$1 is used before ". |
1621 |
"including bsd.port.pre.mk or bsd.port.options.mk.") |
1622 |
if ($optused && $lineno < $pre_mk_line && |
1623 |
$lineno < $options_mk_line); |
1624 |
} |
1625 |
my @options_helpers = qw( |
1626 |
__DUMMY__ |
1627 |
ALL_TARGET |
1628 |
BUILD_DEPENDS |
1629 |
EXTRACT_DEPENDS |
1630 |
FETCH_DEPENDS |
1631 |
LIB_DEPENDS |
1632 |
PKG_DEPENDS |
1633 |
RUN_DEPENDS |
1634 |
CATEGORIES |
1635 |
CFLAGS |
1636 |
CMAKE_OFF |
1637 |
CMAKE_ON |
1638 |
CMAKE_BOOL_OFF |
1639 |
CMAKE_BOOL |
1640 |
CONFIGURE_ENABLE |
1641 |
CONFIGURE_ENV |
1642 |
CONFIGURE_OFF |
1643 |
CONFIGURE_ON |
1644 |
CONFIGURE_WITH |
1645 |
CPPFLAGS |
1646 |
CXXFLAGS |
1647 |
DISTFILES |
1648 |
INSTALL_TARGET |
1649 |
LDFLAGS |
1650 |
MAKE_ARGS |
1651 |
MAKE_ENV |
1652 |
EXTRA_PATCHES |
1653 |
PATCHFILES |
1654 |
PATCH_DEPENDS |
1655 |
PATCH_SITES |
1656 |
PLIST_DIRS |
1657 |
PLIST_DIRSTRY |
1658 |
PLIST_FILES |
1659 |
USE |
1660 |
USES |
1661 |
VARS |
1662 |
VARS_OFF |
1663 |
); |
1664 |
|
1665 |
my $m = join("|", @options_helpers); |
1666 |
|
1667 |
if ($makevar{OPTIONS_SUB}) { |
1668 |
if ($makevar{PLIST_FILES}) { |
1669 |
foreach my $i (split(/\s+/, $makevar{PLIST_FILES})) { |
1670 |
while ($i =~ /\%\%([^%]+)\%\%/g) { |
1671 |
push @popt, $1; |
1672 |
} |
1673 |
} |
1674 |
} |
1675 |
if ($makevar{PLIST_DIRS}) { |
1676 |
foreach my $i (split(/\s+/, $makevar{PLIST_DIRS})) { |
1677 |
while ($i =~ /\%\%([^%]+)\%\%/g) { |
1678 |
push @popt, $1; |
1679 |
} |
1680 |
} |
1681 |
} |
1682 |
if (-f 'pkg-plist') { |
1683 |
open(PL, 'pkg-plist'); |
1684 |
my @pcontents = <PL>; |
1685 |
close(PL); |
1686 |
foreach my $i (@pcontents) { |
1687 |
while ($i =~ /\%\%([^%]+)\%\%/g) { |
1688 |
push @popt, $1; |
1689 |
} |
1690 |
} |
1691 |
} |
1692 |
# special cases for PORTDOCS/PORTEXAMPLES |
1693 |
push @popt, "DOCS" if $makevar{PORTDOCS}; |
1694 |
push @popt, "EXAMPLES" if $makevar{PORTEXAMPLES}; |
1695 |
|
1696 |
# uniq(@popt) |
1697 |
my %seen = (); |
1698 |
@popt = grep { !$seen{$_}++ } @popt; |
1699 |
} |
1700 |
foreach my $i (@popt) { |
1701 |
if ($i eq 'PORTDOCS') { |
1702 |
if (!grep(/^DOCS$/, @opt)) { |
1703 |
&perror("FATAL", $file, -1, "PORTDOCS appears in plist ". |
1704 |
"but DOCS is not listed in OPTIONS_DEFINE."); |
1705 |
} |
1706 |
} elsif ($i eq 'PORTEXAMPLES') { |
1707 |
if (!grep(/^EXAMPLES$/, @opt)) { |
1708 |
&perror("FATAL", $file, -1, "PORTEXAMPLES appears in plist ". |
1709 |
"but EXAMPLES is not listed in OPTIONS_DEFINE."); |
1710 |
} |
1711 |
} |
1712 |
} |
1713 |
|
1714 |
foreach my $i ((@opt, @aopt)) { |
1715 |
# skip global options |
1716 |
next if ($i eq 'DOCS' or $i eq 'NLS' or $i eq 'EXAMPLES' or $i eq 'IPV6' or $i eq 'X11' or $i eq 'DEBUG'); |
1717 |
if (!grep(/^$i$/, (@mopt, @popt))) { |
1718 |
if ($whole !~ /\n${i}_($m)(_\w+)?(.)?=[^\n]+/) { |
1719 |
if (!$slaveport) { |
1720 |
&perror("WARN", $file, -1, "$i is listed in ". |
1721 |
"OPTIONS_DEFINE, but no PORT_OPTIONS:M$i appears."); |
1722 |
} else { |
1723 |
&perror("WARN", $file, -1, "$i is listed in ". |
1724 |
"OPTIONS_DEFINE, but no PORT_OPTIONS:M$i appears ". |
1725 |
"in this slave Makefile. Make sure it appears in ". |
1726 |
"the master's Makefile."); |
1727 |
} |
1728 |
} |
1729 |
} |
1730 |
} |
1731 |
|
1732 |
foreach my $i (@mopt) { |
1733 |
if (!grep(/^$i$/, @opt, @aopt)) { |
1734 |
# skip global options |
1735 |
next if ($i eq 'DOCS' or $i eq 'NLS' or $i eq 'EXAMPLES' or $i eq 'IPV6' or $i eq 'X11'); |
1736 |
&perror("WARN", $file, -1, "$i appears in PORT_OPTIONS:M, ". |
1737 |
"but is not listed in OPTIONS_DEFINE."); |
1738 |
} |
1739 |
} |
1740 |
|
1741 |
# |
1742 |
# whole file: check DESKTOP_ENTRIES for ${TRUE}/${FALSE} |
1743 |
# |
1744 |
print "OK: checking DESKTOP_ENTRIES for \${TRUE}/\${FALSE}.\n" if ($verbose); |
1745 |
$desktop_entries = &get_makevar_raw('DESKTOP_ENTRIES'); |
1746 |
if ($desktop_entries =~ /\$\{TRUE}/ or $desktop_entries =~ /\$\{FALSE}/ or |
1747 |
$desktop_entries =~ /\"true\"/ or $desktop_entries =~ /\"false\"/) { |
1748 |
&perror("FATAL", $file, -1, "Use true/false (without quotes) instead of \${TRUE}/\${FALSE} in DESKTOP_ENTRIES."); |
1749 |
} |
1750 |
|
1751 |
# |
1752 |
# whole file: USE_* as a user-settable option |
1753 |
# |
1754 |
print "OK: checking for USE_* as a user-settable option.\n" if ($verbose); |
1755 |
while ($whole =~ /\n\s*\.\s*(?:el)?if[^\n]*?\b(\w*USE_)(\w+)(?![^\n]*\n#?\.error)/g) { |
1756 |
my $lineno = &linenumber($`); |
1757 |
&perror("WARN", $file, $lineno, "is $1$2 a user-settable option? ". |
1758 |
"Consider using WITH_$2 instead.") |
1759 |
if ($1.$2 ne 'USE_GCC'); |
1760 |
} |
1761 |
|
1762 |
# |
1763 |
# whole file: NO_CHECKSUM |
1764 |
# |
1765 |
# XXX Don't compress newlines since it messes up line number calculation. |
1766 |
#$whole =~ s/\n#[^\n]*/\n/g; |
1767 |
#$whole =~ s/\n\n+/\n/g; |
1768 |
print "OK: checking NO_CHECKSUM.\n" if ($verbose); |
1769 |
if ($whole =~ /\nNO_CHECKSUM/) { |
1770 |
my $lineno = &linenumber($`); |
1771 |
&perror("FATAL", $file, $lineno, "NO_CHECKSUM is a user ". |
1772 |
"variable and is not to be set in a port's Makefile."); |
1773 |
} |
1774 |
|
1775 |
# |
1776 |
# whole file: MACHINE_ARCH |
1777 |
# |
1778 |
print "OK: checking MACHINE_ARCH.\n" if ($verbose); |
1779 |
if ($whole =~ /\nMACHINE_ARCH/) { |
1780 |
my $lineno = &linenumber($`); |
1781 |
&perror("FATAL", $file, $lineno, "MACHINE_ARCH should never be ". |
1782 |
"overridden."); |
1783 |
} |
1784 |
|
1785 |
# |
1786 |
# whole file: DEPRECATED |
1787 |
# |
1788 |
print "OK: checking DEPRECATED.\n" if ($verbose); |
1789 |
if ($whole =~ /\nDEPRECATED[+?]?=[ \t]*"/ && |
1790 |
$whole !~ /\nDEPRECATED[+?]?=[ \t]*"\$\{BROKEN\}"/) { |
1791 |
my $lineno = &linenumber($`); |
1792 |
&perror("WARN", $file, $lineno, "DEPRECATED messages should not ". |
1793 |
"be quoted unless they are exactly \"\${BROKEN}\"."); |
1794 |
} |
1795 |
if ($whole =~ /\nDEPRECATED[+?]?=[^"]*\$\{BROKEN\}/) { |
1796 |
my $lineno = &linenumber($`); |
1797 |
&perror("WARN", $file, $lineno, "\"\${BROKEN}\" must be quoted ". |
1798 |
"when it is the source of DEPRECATED."); |
1799 |
} |
1800 |
|
1801 |
# |
1802 |
# whole file: BROKEN et al. |
1803 |
# |
1804 |
my ($var); |
1805 |
foreach $var (qw(IGNORE BROKEN COMMENT FORBIDDEN MANUAL_PACKAGE_BUILD NO_CDROM NO_PACKAGE RESTRICTED)) { |
1806 |
print "OK: checking ${var}.\n" if ($verbose); |
1807 |
if ($whole =~ /\n${var}[+?]?=[ \t]+"/) { |
1808 |
my $lineno = &linenumber($`); |
1809 |
&perror("WARN", $file, $lineno, "${var} messages should not ". |
1810 |
"be quoted."); |
1811 |
} |
1812 |
} |
1813 |
|
1814 |
if ($makevar{COMMENT} =~ /^An? / || $makevar{COMMENT} =~ /^The /) { |
1815 |
&perror("WARN", $file, -1, "COMMENT is not supposed to begin with ". |
1816 |
"'A ', 'An ', or 'The '."); |
1817 |
} |
1818 |
|
1819 |
if ($whole =~ /\nIGNORE[+?]?=[ \t]+[^a-z \t]/ || |
1820 |
$whole =~ /^IGNORE[+?]?=[ \t]+.*\.$/m) { |
1821 |
my $lineno = &linenumber($`); |
1822 |
&perror("WARN", $file, $lineno, "IGNORE messages should begin ". |
1823 |
"with a lowercase letter and end without a period."); |
1824 |
} |
1825 |
|
1826 |
if ($whole =~ /\nBROKEN[+?]=[ \t]+[^a-z \t]/ || |
1827 |
$whole =~ /^BROKEN[+?]?=[ \t]+.*\.$/m) { |
1828 |
my $lineno = &linenumber($`); |
1829 |
&perror("WARN", $file, $lineno, "BROKEN messages should begin ". |
1830 |
"with a lowercase letter and end without a period."); |
1831 |
} |
1832 |
|
1833 |
# |
1834 |
# whole file: PKGNAME |
1835 |
# |
1836 |
print "OK: checking PKGNAME.\n" if ($verbose); |
1837 |
if ($whole =~ /\nPKGNAME.?=/) { |
1838 |
my $lineno = &linenumber($`); |
1839 |
&perror("FATAL", $file, $lineno, "PKGNAME is obsoleted by PORTNAME, ". |
1840 |
"PORTVERSION, PKGNAMEPREFIX and PKGNAMESUFFIX."); |
1841 |
} |
1842 |
|
1843 |
# |
1844 |
# whole file: MAKE_JOBS_UNSAFE |
1845 |
# |
1846 |
print "OK: checking for MAKE_JOBS_UNSAFE in combination with NO_BUILD.\n" if ($verbose); |
1847 |
if ($whole =~ /\nMAKE_JOBS_UNSAFE.?=/) { |
1848 |
my $matched = $1; |
1849 |
if ($whole =~ /\nNO_BUILD.?=/) { |
1850 |
my $lineno = &linenumber($`); |
1851 |
&perror("WARN", $file, $lineno, "MAKE_JOBS_UNSAFE should not ". |
1852 |
"be used in combination with NO_BUILD. You ". |
1853 |
"should remove MAKE_JOBS_UNSAFE from your Makefile."); |
1854 |
} |
1855 |
} |
1856 |
|
1857 |
# |
1858 |
# whole file: Check if some macros are sorted |
1859 |
# |
1860 |
my @macros_to_sort = qw( |
1861 |
ONLY_FOR_ARCHS |
1862 |
NOT_FOR_ARCHS |
1863 |
); |
1864 |
print "OK: checking to see if certain macros are sorted.\n" if ($verbose); |
1865 |
foreach my $sorted_macro (@macros_to_sort) { |
1866 |
while ($whole =~ /\n$sorted_macro.?=\s*(.+)\n/g) { |
1867 |
my $lineno = &linenumber($`); |
1868 |
my $srex = $1; |
1869 |
my @smacros = sort(split / /, $srex); |
1870 |
if (join(" ", @smacros) ne $srex) { |
1871 |
&perror("WARN", $file, $lineno, "the arguments to $sorted_macro ". |
1872 |
"are not sorted. Please consider sorting them."); |
1873 |
} |
1874 |
} |
1875 |
} |
1876 |
|
1877 |
# |
1878 |
# whole file: USE_GNOME=pkgconfig |
1879 |
# |
1880 |
print "OK: checking for USE_GNOME=pkgconfig.\n" if ($verbose); |
1881 |
if ($makevar{USE_GNOME} =~ /pkgconfig/) { |
1882 |
&perror("WARN", $file, -1, "USE_GNOME=pkgconfig is now obsolete. ". |
1883 |
"Use USES[+]=pkgconfig instead."); |
1884 |
} |
1885 |
|
1886 |
# |
1887 |
# whole file: using INSTALLS_ICONS when it is not wanted |
1888 |
# |
1889 |
if (!($makevar{INSTALLS_ICONS} eq '') && |
1890 |
!needs_installs_icons()) { |
1891 |
&perror("WARN", $file, -1, "INSTALLS_ICONS is set, but should not be."); |
1892 |
} |
1893 |
|
1894 |
# |
1895 |
# whole file: EXPIRATION_DATE |
1896 |
# |
1897 |
print "OK: checking for valid EXPIRATION_DATE.\n" if ($verbose); |
1898 |
my $edate; |
1899 |
if (($edate) = ($whole =~ m/\nEXPIRATION_DATE\??=[ \t]*([^\n]*)\n/)) { |
1900 |
my $lineno = &linenumber($`); |
1901 |
my $ndate = $edate; |
1902 |
if ($ndate eq '' || length $ndate < 10) { |
1903 |
$ndate = '0000-00-00'; |
1904 |
} |
1905 |
if ($ndate ne strftime("%Y-%m-%d", 0, 0, 0, |
1906 |
substr($ndate, 8, 2), |
1907 |
substr($ndate, 5, 2) - 1, |
1908 |
substr($ndate, 0, 4) - 1900)) { |
1909 |
&perror("FATAL", $file, $lineno, "EXPIRATION_DATE ($edate) is ". |
1910 |
"either not in YYYY-MM-DD format or it is not a valid ". |
1911 |
"date."); |
1912 |
} |
1913 |
} |
1914 |
|
1915 |
# |
1916 |
# whole file: IS_INTERACTIVE/NOPORTDOCS|PORT_OPTIONS:MDOCS |
1917 |
# |
1918 |
print "OK: checking IS_INTERACTIVE.\n" if ($verbose); |
1919 |
if ($whole =~ /\nIS_INTERACTIVE/) { |
1920 |
if ($whole !~ /defined\((BATCH|FOR_CDROM)\)/) { |
1921 |
my $lineno = &linenumber($`); |
1922 |
&perror("WARN", $file, $lineno, "use of IS_INTERACTIVE ". |
1923 |
"discouraged. provide batch mode by using BATCH and/or ". |
1924 |
"FOR_CDROM."); |
1925 |
} |
1926 |
} |
1927 |
print "OK: checking for use of PORT_OPTIONS:MDOCS.\n" if ($verbose); |
1928 |
if ($sharedocused && $whole =~ /PORT_OPTIONS:MDOCS/) { |
1929 |
$docsused++; |
1930 |
} |
1931 |
print "OK: checking for use of NOPORTDOCS.\n" if ($verbose); |
1932 |
if ($whole =~ /defined\s*\(?NOPORTDOCS\)?/ || |
1933 |
$whole =~ /def\s*\(?NOPORTDOCS\)?/) { |
1934 |
my $lineno = &linenumber($`); |
1935 |
&perror("WARN", $file, $lineno, "NOPORTDOCS is deprecated. Please ". |
1936 |
"use PORT_OPTIONS:MDOCS instead."); |
1937 |
} |
1938 |
print "OK: checking for use of NOPORTEXAMPLES.\n" if ($verbose); |
1939 |
if ($whole =~ /defined\s*\(?NOPORTEXAMPLES\)?/ || |
1940 |
$whole =~ /def\s*\(?NOPORTEXAMPLES\)?/) { |
1941 |
my $lineno = &linenumber($`); |
1942 |
&perror("WARN", $file, $lineno, "NOPORTEXAMPLES is deprecated. Please ". |
1943 |
"use PORT_OPTIONS:MEXAMPLES instead."); |
1944 |
} |
1945 |
if ($sharedocused && $whole !~ /defined\s*\(?NOPORTDOCS\)?/ |
1946 |
&& $whole !~ /def\s*\(?NOPORTDOCS\)?/) { |
1947 |
if ($docsused == 1 |
1948 |
&& $whole !~ m#(\$[\{\(]PREFIX[\}\)]|$localbase)/share/doc/#) { |
1949 |
&perror("WARN", $file, -1, "you should only use \".if \${PORT_OPTIONS:MDOCS}\" to wrap ". |
1950 |
"installation of files into $localbase/share/doc if the". |
1951 |
" collection of files is large and it takes considerable time". |
1952 |
" to copy."); |
1953 |
} |
1954 |
} else { |
1955 |
$docsused++; |
1956 |
} |
1957 |
if ($docsused > 1) { |
1958 |
&perror("FATAL", $file, -1, "Both NOPORTDOCS and PORT_OPTIONS:MDOCS are found. ". |
1959 |
"Remove one or another."); |
1960 |
} |
1961 |
print "OK: checking for use of NOPORTDOCS.\n" if ($verbose); |
1962 |
if ($whole =~ /NOPORTDOCS/) { |
1963 |
my $lineno = &linenumber($`); |
1964 |
&perror("WARN", $file, $lineno, "NOPORTDOCS found. Consider ". |
1965 |
"using PORT_OPTIONS:MDOCS."); |
1966 |
} |
1967 |
|
1968 |
# |
1969 |
# whole file: check for USES[+]=gettext |
1970 |
# |
1971 |
print "OK: checking for USES=gettext without PORT_OPTIONS:MNLS.\n" if ($verbose); |
1972 |
if ($makevar{USES} =~ /\bgettext\b/ && $whole !~ /PORT_OPTIONS:MNLS/ |
1973 |
&& $whole !~ /NLS_USES=.*\bgettext\b/) { |
1974 |
&perror("WARN", $file, -1, "Consider adding support for a NLS ". |
1975 |
"knob to conditionally disable gettext support."); |
1976 |
} |
1977 |
|
1978 |
# |
1979 |
# whole file: check for deprecated commands |
1980 |
# |
1981 |
print "OK: checking for deprecated macros.\n" if $verbose; |
1982 |
|
1983 |
%deprecated = ( |
1984 |
USE_RCORDER => 'USE_RC_SUBR', |
1985 |
); |
1986 |
|
1987 |
@deplist = (\%deprecated); |
1988 |
|
1989 |
for my $dlst (@deplist) { |
1990 |
my $hurl = $dlst->{'__HELP__'}; |
1991 |
foreach my $depmacro (keys %{$dlst}) { |
1992 |
if ($whole =~ /\n($depmacro)[+?:!]?=/) { |
1993 |
my $derror = "$depmacro is ". |
1994 |
"deprecated, use $dlst->{$1} instead"; |
1995 |
if (defined($hurl)) { |
1996 |
$derror .= " (see $hurl for more details)"; |
1997 |
} |
1998 |
&perror("FATAL", $file, -1, $derror); |
1999 |
} |
2000 |
} |
2001 |
} |
2002 |
|
2003 |
# |
2004 |
# whole file: DOS line endings |
2005 |
# |
2006 |
print "OK: checking for DOS line ending removal.\n" if ($verbose); |
2007 |
if ($whole =~ / |
2008 |
/ || $whole =~ /:cntrl:/) { |
2009 |
my $lineno = &linenumber($`); |
2010 |
&perror("WARN", $file, $lineno, "Possible manual removal of DOS ". |
2011 |
"line endings found. Consider defining USES=dos2unix instead."); |
2012 |
} |
2013 |
|
2014 |
# |
2015 |
# whole file: direct use of command names |
2016 |
# |
2017 |
my %cmdnames = (); |
2018 |
print "OK: checking direct use of command names.\n" if ($verbose); |
2019 |
foreach my $i (qw( |
2020 |
awk basename brandelf cat chmod chown cp cpio dialog dirname egrep expr |
2021 |
false file find gmake grep gzcat ldconfig ln md5 mkdir mv objcopy paste patch |
2022 |
pax perl printf rm rmdir ruby sed sdl-config sh sort sysctl touch tr which |
2023 |
xargs xmkmf |
2024 |
)) { |
2025 |
$cmdnames{$i} = "\$\{\U$i\E\}"; |
2026 |
} |
2027 |
$cmdnames{'echo'} = '${ECHO_CMD} or ${ECHO_MSG}'; |
2028 |
$cmdnames{'env'} = '${SETENV}'; |
2029 |
$cmdnames{'gunzip'} = '${GUNZIP_CMD}'; |
2030 |
$cmdnames{'gzip'} = '${GZIP_CMD}'; |
2031 |
$cmdnames{'install'} = '${INSTALL_foobar}'; |
2032 |
$cmdnames{'python'} = '${PYTHON_CMD}'; |
2033 |
$cmdnames{'sdl-config'} = '${SDL_CONFIG}'; |
2034 |
$cmdnames{'strip'} = '${STRIP_CMD}'; |
2035 |
$cmdnames{'unzip'} = '${UNZIP_CMD}'; |
2036 |
$cmdnames{'pkg_create'} = '${PKG_CMD}'; |
2037 |
foreach my $i (qw(aclocal autoconf autoheader automake autoreconf autoupdate autoscan ifnames libtoolize)) { |
2038 |
$autocmdnames{$i} = "\$\{" . ( ( $i !~ /auto|aclocal/ ) ? "AUTO" : "" ) . "\U$i\E\}"; |
2039 |
} |
2040 |
# |
2041 |
# ignore parameter string to echo command. |
2042 |
# note that we leave the command as is, since we need to check the |
2043 |
# use of echo itself. |
2044 |
$j = $whole; |
2045 |
$j =~ s/([ \t][\@\-]{0,2})(echo|\$[\{\(]ECHO[\}\)]|\$[\{\(]ECHO_MSG[\}\)])[ \t]+(?:"(?:\\'|\\"|[^"])*"|'(?:\\'|\\"|[^'])*')[ \t]*;?(\n?)/$1$2;$3/g; #" |
2046 |
# ignore variables names in .for loops, but not what's at the end |
2047 |
# of the for loop |
2048 |
$j =~ s/(\.for +)([^ ]*)( .*)/$1$3/; |
2049 |
foreach my $i (keys %cmdnames) { |
2050 |
# XXX This is a hack. Really, we should break $j up into individual |
2051 |
# lines, and go through each one. |
2052 |
while ($j =~ /^(.*\b$i\b.*)$/gm) { |
2053 |
my $lineno = &linenumber($`); |
2054 |
my $curline = $1; |
2055 |
my $dte_test = $curline; |
2056 |
$dte_test =~ s/^\s+//g; |
2057 |
if ($desktop_entries =~ /\Q$dte_test\E$/) { |
2058 |
next; |
2059 |
} |
2060 |
if ($curline =~ /(?:^|\s)[\@\-]{0,2}$i(?:$|\s)/ |
2061 |
&& $curline !~ /^[A-Z]+_TARGET[?+]?=[^\n]+$i/m |
2062 |
&& $curline !~ /^[A-Z]+_INSTALL_TARGET[?+]?=[^\n]+$i/m |
2063 |
&& $curline !~ /^IGNORE(_[\w\d]+)?(.)?=[^\n]+$i/m |
2064 |
&& $curline !~ /^BROKEN(_[\w\d]+)?(.)?=[^\n]+$i/m |
2065 |
&& $curline !~ /^RESTRICTED(.)?=[^\n]+$i/m |
2066 |
&& $curline !~ /^NO_PACKAGE(.)?=[^\n]+$i/m |
2067 |
&& $curline !~ /^NO_CDROM(.)?=[^\n]+$i/m |
2068 |
&& $curline !~ /^MAINTAINER(.)?=[^\n]+$i/m |
2069 |
&& $curline !~ /^CATEGORIES(.)?=[^\n]+$i/m |
2070 |
&& $curline !~ /^(\w+)?USES(.)?=[^\n]+$i/m |
2071 |
&& $curline !~ /^WX_COMPS(.)?=[^\n]+$i/m |
2072 |
&& $curline !~ /^ONLY_FOR_ARCHS_REASON(_[\w\d]+)?(.)?=[^\n]+$i/m |
2073 |
&& $curline !~ /^NOT_FOR_ARCHS_REASON(_[\w\d]+)?(.)?=[^\n]+$i/m |
2074 |
&& $curline !~ /^SHEBANG_FILES(.)?=[^\n]+$i/m |
2075 |
&& $curline !~ /^[A-Z0-9_]+_DESC=[^\n]+$i/m |
2076 |
&& $curline !~ /#.*?$i/m |
2077 |
&& $curline !~ /^\s*#.+$/m |
2078 |
&& $curline !~ /\$\{MAKE_CMD\}.*\binstall\b/m |
2079 |
&& $curline !~ /\-\-$i/m |
2080 |
&& $curline !~ /^COMMENT(.)?=[^\n]+$i/m) { |
2081 |
&perror("WARN", $file, $lineno, "possible direct use of ". |
2082 |
"command \"$i\" found. use ". |
2083 |
"$cmdnames{$i} instead."); |
2084 |
} |
2085 |
} |
2086 |
} |
2087 |
|
2088 |
foreach my $i (keys %autocmdnames) { |
2089 |
# XXX Same hack as above. |
2090 |
while ($j =~ /^(.*(\b$i\d*).*)$/gm) { |
2091 |
my $lm = $1; |
2092 |
my $sm = $2; |
2093 |
my $lineno = &linenumber($`); |
2094 |
if ($lm =~ /(^|\s+)[\@\-]{0,2}($i\d*)\b/ |
2095 |
&& $lm !~ /^[A-Z]+_TARGET[?+]?=[^\n]+($i\d*)/m |
2096 |
&& $lm !~ /^IGNORE(.)?=[^\n]+($i\d*)/m |
2097 |
&& $lm !~ /^BROKEN(.)?=[^\n]+($i\d*)/m |
2098 |
&& $lm !~ /^RESTRICTED(.)?=[^\n]+($i\d*)/m |
2099 |
&& $lm !~ /^NO_PACKAGE(.)?=[^\n]+($i\d*)/m |
2100 |
&& $lm !~ /^NO_CDROM(.)?=[^\n]+($i\d*)/m |
2101 |
&& $lm !~ /^MAINTAINER(.)?=[^\n]+($i\d*)/m |
2102 |
&& $lm !~ /^CATEGORIES(.)?=[^\n]+($i\d*)/m |
2103 |
&& $lm !~ /^USES(.)?=[^\n]+$i/m |
2104 |
&& $lm !~ /^[A-Z0-9_]+_DESC=[^\n]+($i\d*)/m |
2105 |
&& $lm !~ /^SHEBANG_FILES(.)?=[^\n]+($i\d*)/m |
2106 |
&& $lm !~ /^USE_AUTOTOOLS(.)?=[^\n]+($i\d*)/m |
2107 |
&& $lm !~ /^\s*#.+$/m |
2108 |
&& $lm !~ /^COMMENT(.)?=[^\n]+($i\d*)/m) { |
2109 |
&perror("WARN", $file, $lineno, "possible direct use of ". |
2110 |
"command \"$sm\" found. Use $autocmdnames{$i} ". |
2111 |
"instead and set according USE_AUTOTOOLS=<tool> macro"); |
2112 |
} |
2113 |
} |
2114 |
} |
2115 |
|
2116 |
if ($makevar{'USE_AUTOTOOLS'} =~ /\blibtool\b/) { |
2117 |
&perror("WARN", $file, -1, "USE_AUTOTOOLS=libtool is deprecated. ". |
2118 |
"Use USES=libtool instead."); |
2119 |
} |
2120 |
|
2121 |
# |
2122 |
# whole file: check for use of paths that have macro replacements |
2123 |
# |
2124 |
my %pathnames = (); |
2125 |
print "OK: checking for paths that have macro replacements.\n" |
2126 |
if ($verbose); |
2127 |
$pathnames{'$\{PREFIX\}/share/java/classes'} = 'JAVADIR'; |
2128 |
$pathnames{'$\{PREFIX\}/share/java'} = 'JAVASHAREDIR'; |
2129 |
foreach my $i (keys %pathnames) { |
2130 |
my $lineno = &linenumber($`); |
2131 |
if ($j =~ m|$i|gm) { |
2132 |
&perror("FATAL", $file, $lineno, "you should use ". |
2133 |
"$pathnames{$i} rather than $i"); |
2134 |
} |
2135 |
} |
2136 |
|
2137 |
# |
2138 |
# whole file: ${GZIP_CMD} -9 (or any other number) |
2139 |
# |
2140 |
print "OK: checking for compression arguments passed to \${GZIP_CMD}.\n" |
2141 |
if ($verbose); |
2142 |
if ($j =~ /\$\{GZIP_CMD}\s+-(\w+(\s+-)?)*(\d)/) { |
2143 |
my $lineno = &linenumber($`); |
2144 |
&perror("WARN", $file, $lineno, "possible use of \"\${GZIP_CMD} -$3\" ". |
2145 |
"found. \${GZIP_CMD} includes \"-\${GZIP}\" which ". |
2146 |
"sets the compression level."); |
2147 |
} |
2148 |
|
2149 |
# |
2150 |
# whole file: ${CHMOD} used |
2151 |
# |
2152 |
print "OK: checking for \${CHMOD}.\n" if ($verbose); |
2153 |
if ($j =~ /\n\s*\$\{CHMOD}/) { |
2154 |
my $lineno = &linenumber($`); |
2155 |
&perror("WARN", $file, $lineno, "possible use of \"\${CHMOD}\" ". |
2156 |
"found. Use @(owner,group,mode) syntax or \@owner/\@group ". |
2157 |
"operators in pkg-plist instead."); |
2158 |
} |
2159 |
|
2160 |
# |
2161 |
# whole file: ${INSTALL} -o | -g used |
2162 |
# |
2163 |
print "OK: checking for \${INSTALL} -o | -g.\n" if ($verbose); |
2164 |
if ($j =~ /\n\s*\$\{INSTALL}(.*-\b(o|g)\b.*)/) { |
2165 |
my $lineno = &linenumber($`); |
2166 |
&perror("WARN", $file, $lineno, "possible use of \"\${INSTALL} -o | -g\" ". |
2167 |
"found. Use @(owner,group,mode) syntax or \@owner/\@group ". |
2168 |
"operators in pkg-plist instead."); |
2169 |
} |
2170 |
|
2171 |
# |
2172 |
# whole file: ${MKDIR} -p |
2173 |
# |
2174 |
print "OK: checking for \${MKDIR} -p.\n" |
2175 |
if ($verbose); |
2176 |
if ($j =~ /\$\{MKDIR}\s+-p/) { |
2177 |
my $lineno = &linenumber($`); |
2178 |
&perror("WARN", $file, $lineno, "possible use of \"\${MKDIR} -p\" ". |
2179 |
"found. \${MKDIR} includes ". |
2180 |
"\"-p\" by default."); |
2181 |
} |
2182 |
|
2183 |
# |
2184 |
# check for use of ${FIND} ... ${XARGS} ${RM} |
2185 |
# |
2186 |
print "OK: checking for instances of \${FIND} ... \${XARGS} \${RM}.\n" |
2187 |
if ($verbose); |
2188 |
if ($j =~ /\$\{FIND\}.*\|.*\$\{XARGS\}.*\$\{RM\}/) { |
2189 |
my $lineno = &linenumber($`); |
2190 |
&perror("WARN", $file, $lineno, "possible use of ". |
2191 |
"\"\${FIND} ... \${XARGS} \${RM}\" when ". |
2192 |
"\"\${FIND} ... -delete\" will work."); |
2193 |
} |
2194 |
|
2195 |
# |
2196 |
# whole file: ${MACHINE_ARCH} |
2197 |
# |
2198 |
print "OK: checking for instances of \${MACHINE_ARCH} being test.\n" |
2199 |
if ($verbose); |
2200 |
if ($j =~ /\$\{MACHINE_ARCH}\s*[!=]=/) { |
2201 |
my $lineno = &linenumber($`); |
2202 |
&perror("FATAL", $file, $lineno, "MACHINE_ARCH should never be tested ". |
2203 |
"directly; use ARCH instead."); |
2204 |
} |
2205 |
|
2206 |
# |
2207 |
# whole file: full path name |
2208 |
# |
2209 |
&abspathname($whole, $file); |
2210 |
|
2211 |
# |
2212 |
# whole file: SITE_PERL |
2213 |
# |
2214 |
print "OK: checking SITE_PERL.\n" if ($verbose); |
2215 |
if ($whole =~ /\nSITE_PERL[?:]?=/) { |
2216 |
my $lineno = &linenumber($`); |
2217 |
&perror("FATAL", $file, $lineno, "use of SITE_PERL discouraged. ". |
2218 |
"it is set in bsd.port.mk."); |
2219 |
} |
2220 |
|
2221 |
# |
2222 |
# whole file: ${LOCALBASE}/lib/perl5/site_perl |
2223 |
# |
2224 |
if ($j =~ m'\$\{(?:LOCALBASE|PREFIX)}/lib/perl5/site_perl') { |
2225 |
my $lineno = &linenumber($`); |
2226 |
if ($1 !~ /PREFIX/) { |
2227 |
&perror("WARN", $file, $lineno, "possible use of \"\${LOCALBASE}/lib/perl5/site_perl\" ". |
2228 |
"found. use \"\${SITE_PERL}\" instead."); |
2229 |
} else { |
2230 |
&perror("WARN", $file, $lineno, "possible use of \"\${PREFIX}/lib/perl5/site_perl\" ". |
2231 |
"found. use \"\${PREFIX}/\${SITE_PERL_REL}\" instead."); |
2232 |
} |
2233 |
} |
2234 |
|
2235 |
# |
2236 |
# whole file: check for misuse of STAGE with SITE_PERL and SITE_ARCH |
2237 |
# |
2238 |
if ($j =~ m'\$\{FAKE_DESTDIR\}\${SITE_PERL}') { |
2239 |
my $lineno = &linenumber($`); |
2240 |
&perror("WARN", $file, $lineno, "\${FAKE_DESTDIR}\${SITE_PERL} should be ". |
2241 |
"replaced by \${FAKE_DESTDIR}\${PREFIX}/\${SITE_PERL_REL}."); |
2242 |
} |
2243 |
|
2244 |
if ($j =~ m'\$\{FAKE_DESTDIR}\$\{SITE_ARCH}') { |
2245 |
my $lineno = &linenumber($`); |
2246 |
&perror("WARN", $file, $lineno, "\${FAKE_DESTDIR}\${SITE_ARCH} should be ". |
2247 |
"replaced by \${FAKE_DESTDIR}\${PREFIX}/\${SITE_ARCH_REL}."); |
2248 |
} |
2249 |
|
2250 |
# |
2251 |
# whole file: USE_GNOME check |
2252 |
# |
2253 |
if ($whole =~ /^USE_GNOME[?:]?=\s*(.*)$/m) { |
2254 |
if ($1 =~ /gnomehack/) { |
2255 |
$use_gnome_hack = 1; |
2256 |
} |
2257 |
} |
2258 |
|
2259 |
# |
2260 |
# whole file: USE_KDE check |
2261 |
# |
2262 |
if ($whole =~ /^USE_KDE[?:]?=\s*(.*)$/m) { |
2263 |
if ($makevar{USES} !~ /\bkde:[45]/) { |
2264 |
my $lineno = &linenumber($`); |
2265 |
&perror("WARN", $file, $lineno, "USE_KDE is defined without ". |
2266 |
"defining USES=kde:[45]"); |
2267 |
} |
2268 |
} |
2269 |
|
2270 |
# |
2271 |
# whole file: USES=pyqt:5 |
2272 |
# |
2273 |
if ($makevar{USES} =~ /\bpyqt:5/ && $whole !~ /^USE_PYQT[?:]?=\s(.*)$/m) { |
2274 |
&perror("WARN", $file, -1, "When USES=pyqt:5 is defined, you must also define ". |
2275 |
"USE_PYQT=xxxx"); |
2276 |
} |
2277 |
|
2278 |
# |
2279 |
# whole file: USE_GCC checks |
2280 |
# |
2281 |
if ($whole =~ /^USE_GCC[?:]?=\s*([^\s#]*).*$/m) { |
2282 |
my $lineno = &linenumber($`); |
2283 |
my $gcc_val = $1; |
2284 |
if ($gcc_val eq 'any' || $gcc_val eq 'yes') { |
2285 |
# Just accept these two. |
2286 |
} elsif ($gcc_val !~ /\+/) { |
2287 |
&perror("WARN", $file, $lineno, "Setting a specific version for ". |
2288 |
"USE_GCC should only be done as a last resort. Unless you ". |
2289 |
"have confirmed this port does not build with later ". |
2290 |
"versions of GCC, please use USE_GCC=$gcc_val+."); |
2291 |
} |
2292 |
} |
2293 |
|
2294 |
# |
2295 |
# whole file: USE_JAVA check |
2296 |
# |
2297 |
if ($whole =~ /^USE_JAVA[?:]?=\s*(.*)$/m) { |
2298 |
$use_java = 1; |
2299 |
} |
2300 |
|
2301 |
# |
2302 |
# whole file: USE_ANT check |
2303 |
# |
2304 |
if ($whole =~ /^USE_ANT[?:]?=\s*(.*)$/m) { |
2305 |
$use_ant = 1; |
2306 |
} |
2307 |
|
2308 |
# |
2309 |
# whole file: USE_JAVA not defined, but other Java components are requested |
2310 |
# |
2311 |
if (!$use_java && ($use_ant || $whole =~ /^JAVA_VERSION[?:]?=\s*(.*)$/m || |
2312 |
$whole =~ /^JAVA_OS[?:]?=\s*(.*)$/m || |
2313 |
$whole =~ /^JAVA_VENDOR[?:]?=\s*(.*)$/m || |
2314 |
$whole =~ /^JAVA_RUN[?:]?=\s*(.*)$/m || |
2315 |
$whole =~ /^JAVA_BUILD[?:]?=\s*(.*)$/m)) { |
2316 |
&perror("FATAL", $file, -1, "the port uses Java features, but USE_JAVA ". |
2317 |
"is not defined"); |
2318 |
} |
2319 |
|
2320 |
# |
2321 |
# whole file: check for USE_ANT and USES=gmake both defined |
2322 |
# |
2323 |
if ($use_ant && $makevar{USES} =~ /\bgmake\b/) { |
2324 |
&perror("WARN", $file, -1, "a port shall not define both USE_ANT ". |
2325 |
"and USES[+]=gmake"); |
2326 |
} |
2327 |
|
2328 |
# |
2329 |
# whole file: check for USE_APACHE=yes |
2330 |
# |
2331 |
if ($whole =~ /^USE_APACHE[?:]?=\s*(yes)$/m) { |
2332 |
&perror("FATAL", $file, -1, "Use USE_APACHE=VERSION ". |
2333 |
"(where version can be found in \${PORTSDIR}/Mk/bsd.apache.mk) ". |
2334 |
"instead of yes"); |
2335 |
} |
2336 |
|
2337 |
# |
2338 |
# whole file: check for WITH_APACHE\d+ |
2339 |
# |
2340 |
if ($whole =~ /WITH_APACHE\d+/) { |
2341 |
&perror("FATAL", $file, -1, "Use WITH_APACHE=yes and .if ". |
2342 |
"\${APACHE_VERSION} [==|<|>] 13|20|22|24"); |
2343 |
} |
2344 |
|
2345 |
# |
2346 |
# whole file: check for JAVA_BUILD and NO_BUILD |
2347 |
# |
2348 |
if ($whole =~ /^NO_BUILD[?:]?=\s*(.*)$/m && |
2349 |
$whole =~ /^JAVA_BUILD[?:]?=\s*(.*)$/m) { |
2350 |
&perror("FATAL", $file, -1, "JAVA_BUILD and NO_BUILD cannot be set ". |
2351 |
"at the same time"); |
2352 |
} |
2353 |
|
2354 |
# |
2355 |
# whole file: check for reassignment of ECHO_MSG |
2356 |
# |
2357 |
if ($whole =~ /^ECHO_MSG[?:]?=\s*(.*)$/m) { |
2358 |
&perror("FATAL", $file, -1, "Re-assigning ECHO_MSG can break ". |
2359 |
"``make readme''. Consider using \${PRINTF} directly instead ". |
2360 |
"for custom message output."); |
2361 |
} |
2362 |
|
2363 |
# |
2364 |
# whole file: check for --build, --mandir, and --infodir |
2365 |
# when GNU_CONFIGURE |
2366 |
# |
2367 |
if ($makevar{GNU_CONFIGURE} ne '' && |
2368 |
$makevar{CONFIGURE_ARGS} =~ /--(build|(man|info)dir)/) { |
2369 |
&perror("WARN", $file, -1, "--build, --mandir, and --infodir ". |
2370 |
"are not needed in CONFIGURE_ARGS as they are already set in ". |
2371 |
"bsd.port.mk."); |
2372 |
} |
2373 |
|
2374 |
# |
2375 |
# whole file: check for redundant SHEBANG_LANGs |
2376 |
# |
2377 |
if ($whole =~ /^SHEBANG_LANG[?+]?=\s*(.*)$/m) { |
2378 |
my $sh_lang = $1; |
2379 |
my @shebang_langs = split(/\s+/, $makevar{SHEBANG_LANG} // ''); |
2380 |
my %sh_seen = (); |
2381 |
foreach my $shebang_lang (@shebang_langs) { |
2382 |
if ($sh_seen{$shebang_lang}) { |
2383 |
$sh_seen{$shebang_lang}++; |
2384 |
} else { |
2385 |
$sh_seen{$shebang_lang} = 1; |
2386 |
} |
2387 |
if ($sh_seen{$shebang_lang} > 1 && $sh_lang =~ /\b$shebang_lang\b/) { |
2388 |
&perror("WARN", $file, -1, "$shebang_lang is already included in ". |
2389 |
"SHEBANG_LANG. You should remove this from $file."); |
2390 |
} |
2391 |
} |
2392 |
} |
2393 |
|
2394 |
# |
2395 |
# whole file: CONFIGURE_ENV |
2396 |
# |
2397 |
if ($whole =~ /\nCONFIGURE_ENV[?:+]?=\s*([^\\\n]+(\\\n[^\\\n]+)*)/) { |
2398 |
my $configure_env = $1; |
2399 |
my $cflags = undef; |
2400 |
my $cxxflags = undef; |
2401 |
if ($configure_env =~ /\bCFLAGS="([^"]+)"/ || |
2402 |
$configure_env =~ /\bCFLAGS='([^']+)'/ || |
2403 |
$configure_env =~ /\bCFLAGS=(\S+)/) { |
2404 |
$cflags = $1; |
2405 |
} |
2406 |
if ($configure_env =~ /\bCXXFLAGS="([^"]+)"/ || |
2407 |
$configure_env =~ /\bCXXFLAGS='([^']+)'/ || |
2408 |
$configure_env =~ /\bCXXFLAGS=(\S+)/) { |
2409 |
$cxxflags = $1; |
2410 |
} |
2411 |
|
2412 |
if (defined($cflags) || defined($cxxflags)) { |
2413 |
&perror("WARN", $file, -1, "CFLAGS/CXXFLAGS are not needed in ". |
2414 |
"CONFIGURE_ENV as they are already added there in bsd.port.mk."); |
2415 |
} |
2416 |
|
2417 |
if ($makevar{GNU_CONFIGURE} ne '') { |
2418 |
if ((defined($cflags) && $cflags =~ /-I/) || |
2419 |
(defined($cxxflags) && $cxxflags =~ /-I/)) { |
2420 |
&perror("WARN", $file, -1, "Consider passing include paths ". |
2421 |
"to configure via the CPPFLAGS macro ". |
2422 |
"(i.e. CPPFLAGS+=-I...)"); |
2423 |
} |
2424 |
} |
2425 |
|
2426 |
if (defined($cflags) && $cflags !~ /\$\{CFLAGS/) { |
2427 |
&perror("FATAL", $file, -1, "CFLAGS are clobbered in ". |
2428 |
"CONFIGURE_ENV. Alter CFLAGS in the Makefile with ". |
2429 |
"CFLAGS+=... instead"); |
2430 |
} |
2431 |
|
2432 |
if (defined($cxxflags) && $cxxflags !~ /\$\{CXXFLAGS/) { |
2433 |
&perror("FATAL", $file, -1, "CXXFLAGS are clobbered in ". |
2434 |
"CONFIGURE_ENV. Alter CXXFLAGS in the Makefile with ". |
2435 |
"CXXFLAGS+=... instead"); |
2436 |
} |
2437 |
|
2438 |
if ($configure_env =~ /(FC)=/ || |
2439 |
$configure_env =~ /(F77)=/ || |
2440 |
$configure_env =~ /(FFLAGS)=/) { |
2441 |
&perror("FATAL", $file, -1, "$1 is already ". |
2442 |
"passed in CONFIGURE_ENV via bsd.gcc.mk. If you need to ". |
2443 |
"override the default value, alter $1 in the Makefile ". |
2444 |
"instead with $1=..."); |
2445 |
} |
2446 |
|
2447 |
if ($configure_env =~ /(\bCPPFLAGS)=/) { |
2448 |
&perror("FATAL", $file, -1, "$1 is already ". |
2449 |
"passed in CONFIGURE_ENV via bsd.port.mk. If you need to ". |
2450 |
"override the default value, alter $1 in the Makefile ". |
2451 |
"instead with $1+=..."); |
2452 |
} |
2453 |
|
2454 |
if ($configure_env =~ /(\bLDFLAGS)=/) { |
2455 |
&perror("FATAL", $file, -1, "$1 is already passed in ". |
2456 |
"CONFIGURE_ENV via bsd.port.mk. If you need to ". |
2457 |
"override the default value, alter $1 in the Makefile ". |
2458 |
"instead with $1+=..."); |
2459 |
} |
2460 |
} |
2461 |
|
2462 |
# |
2463 |
# whole file: *FLAGS |
2464 |
# |
2465 |
foreach my $f (qw(CFLAGS CXXFLAGS CPPFLAGS LDFLAGS)) { |
2466 |
if ($whole =~ /^$f=/m) { |
2467 |
&perror("WARN", $file, -1, "$f is overridden in the Makefile ". |
2468 |
"clobbering a value possibly set by a user. Consider ". |
2469 |
"using $f+=... if you want to add or $f:=\${$f:C/...//} ". |
2470 |
"if you want to remove specific flags"); |
2471 |
} |
2472 |
} |
2473 |
|
2474 |
# |
2475 |
# whole file: MAKE_ENV |
2476 |
# |
2477 |
if ($whole =~ /\nMAKE_ENV[?:+]?=\s*([^\\\n]+(\\\n[^\\\n]+)*)/) { |
2478 |
my $make_env = $1; |
2479 |
|
2480 |
if ($make_env =~ /(CPPFLAGS)=/) { |
2481 |
&perror("FATAL", $file, -1, "$1 is already ". |
2482 |
"passed in MAKE_ENV via bsd.port.mk. If you need to ". |
2483 |
"override the default value, alter $1 in the Makefile ". |
2484 |
"instead with $1=..."); |
2485 |
} |
2486 |
} |
2487 |
|
2488 |
# |
2489 |
# slave port check |
2490 |
# |
2491 |
if ($slaveport) { |
2492 |
print "OK: slave port detected, checking for inclusion of $masterdir/Makefile.\n" |
2493 |
if ($verbose); |
2494 |
if ($whole =~ /^\.\s*include\s*[<"]bsd\.port(?:\.post)?\.mk[">]/m) { |
2495 |
&perror("FATAL", $file, -1, "supposedly non-slave port with". |
2496 |
" .CURDIR != MASTERDIR"); |
2497 |
} elsif ($whole =~ /^\.\s*include\s*[<"]bsd\.port\.pre\.mk[">]/m) { |
2498 |
&perror("FATAL", $file, -1, "slave ports may not include". |
2499 |
" bsd.port.pre.mk"); |
2500 |
} |
2501 |
if ($whole !~ /\n\.include\s+"\$\{MASTERDIR\}\/Makefile"\s*$/s) { |
2502 |
&perror("FATAL", $file, -1, "the last line of a slave port's Makefile has to be". |
2503 |
' .include "${MASTERDIR}/Makefile"'); |
2504 |
} |
2505 |
print "OK: checking master port in $masterdir.\n" if ($verbose); |
2506 |
if (! -e "$masterdir/Makefile") { |
2507 |
&perror("WARN", "", -1, "unable to locate master port in $masterdir"); |
2508 |
} |
2509 |
if ($whole !~ /^MASTERDIR=\s*\$\{\.CURDIR\}(?:\/\.\.){1,2}(?:\/[\w\@.+-]+){1,2}\s*$/m) { |
2510 |
&perror("WARN", $file, -1, "slave ports must define MASTERDIR=". |
2511 |
'${.CURDIR}/..(/../<category>)/<port>'); |
2512 |
} |
2513 |
} else { |
2514 |
#$slaveport = 0; |
2515 |
print "OK: non-slave port detected, checking for anything after bsd.port(.post).mk.\n" |
2516 |
if ($verbose); |
2517 |
if ($whole !~ /\n\.include\s+<bsd\.port(?:\.post)?\.mk>\s*$/s) { |
2518 |
&perror("FATAL", $file, -1, "the last line of Makefile has to be". |
2519 |
' .include <bsd.port(.post).mk>'); |
2520 |
} |
2521 |
if ($whole =~ /^MASTERDIR\s*[+?:!]?\s*=/m) { |
2522 |
&perror("WARN", $file, -1, "non-slave ports may not define MASTERDIR"); |
2523 |
} |
2524 |
} |
2525 |
|
2526 |
# |
2527 |
# break the makefile into sections. |
2528 |
# |
2529 |
$tmp = $rawwhole; |
2530 |
$tmp =~ s/\\\n/ /g; |
2531 |
# keep comment, blank line, comment in the same section |
2532 |
$tmp =~ s/(#.*\n)\n+(#.*)/$1$2/g; |
2533 |
@sections = split(/\n\n+/, $tmp); |
2534 |
for ($i = 0; $i <= $#sections; $i++) { |
2535 |
if ($sections[$i] !~ /\n$/) { |
2536 |
$sections[$i] .= "\n"; |
2537 |
} |
2538 |
} |
2539 |
$idx = 0; |
2540 |
|
2541 |
# |
2542 |
# section 1: comment lines. |
2543 |
# |
2544 |
print "OK: checking comment section of $file.\n" if ($verbose); |
2545 |
my @linestocheck = split("\n", <<EOF); |
2546 |
Whom |
2547 |
Date [cC]reated |
2548 |
EOF |
2549 |
|
2550 |
$tmp = $sections[$idx++]; |
2551 |
$tmp = "\n" . $tmp; # to make the begin-of-line check easier |
2552 |
|
2553 |
if ($tmp =~ /\n[^#]/) { |
2554 |
&perror("FATAL", $file, -1, "non-comment line in comment section."); |
2555 |
} |
2556 |
if ($tmp =~ m/Version [rR]equired/) { |
2557 |
&perror("WARN", $file, -1, "Version required is no longer needed in the comment section."); |
2558 |
} |
2559 |
my $tmp2 = ""; |
2560 |
for (split(/\n/, $tmp)) { |
2561 |
$tmp2 .= $_ if (m/\$$rcsidstr/); |
2562 |
} |
2563 |
if ($tmp2 !~ /#(\s+)\$$rcsidstr([^\$]*)\$$/) { |
2564 |
|
2565 |
&perror("FATAL", $file, -1, "no \$$rcsidstr\$ line in comment ". |
2566 |
"section."); |
2567 |
} else { |
2568 |
print "OK: \$$rcsidstr\$ seen in $file.\n" if ($verbose); |
2569 |
if ($1 ne ' ') { |
2570 |
&perror("WARN", $file, -1, "please use single whitespace ". |
2571 |
"right before \$$rcsidstr\$ tag."); |
2572 |
} |
2573 |
if ($2 ne '') { |
2574 |
if ($verbose || $newport) { # XXX |
2575 |
&perror("WARN", $file, -1, |
2576 |
($newport ? 'for new port, ' |
2577 |
: 'is it a new port? if so, '). |
2578 |
"make \$$rcsidstr\$ tag in comment ". |
2579 |
"section empty, to make SVN happy."); |
2580 |
} |
2581 |
} |
2582 |
} |
2583 |
|
2584 |
# |
2585 |
# for the rest of the checks, comment lines are not important. |
2586 |
# |
2587 |
for ($i = 0; $i < scalar(@sections); $i++) { |
2588 |
$sections[$i] = "\n" . $sections[$i]; |
2589 |
$sections[$i] =~ s/\n#[^\n]*//g; |
2590 |
$sections[$i] =~ s/\n\n+/\n/g; |
2591 |
$sections[$i] =~ s/^\n//; |
2592 |
} |
2593 |
|
2594 |
# |
2595 |
# section 2: PORTNAME/PORTVERSION/... |
2596 |
# |
2597 |
print "OK: checking first section of $file (PORTNAME/...).\n" |
2598 |
if ($verbose); |
2599 |
$tmp = $sections[$idx++]; |
2600 |
|
2601 |
# check the order of items. |
2602 |
&checkorder('PORTNAME', $tmp, $file, qw( |
2603 |
PORTNAME PORTVERSION DISTVERSIONPREFIX DISTVERSION DISTVERSIONSUFFIX |
2604 |
PORTREVISION PORTEPOCH CATEGORIES MASTER_SITES MASTER_SITE_SUBDIR |
2605 |
PROJECTHOST PKGNAMEPREFIX PKGNAMESUFFIX DISTNAME EXTRACT_SUFX DISTFILES |
2606 |
DIST_SUBDIR EXTRACT_ONLY |
2607 |
)); |
2608 |
|
2609 |
# check the items that has to be there. |
2610 |
$tmp = "\n" . $tmp; |
2611 |
print "OK: checking PORTNAME/PORTVERSION/DISTVERSION.\n" if ($verbose); |
2612 |
if ($tmp !~ /\nPORTNAME(.)?=/) { |
2613 |
&perror("FATAL", $file, -1, "PORTNAME has to be there.") unless ($slaveport && $makevar{PORTNAME} ne ''); |
2614 |
} elsif (defined $1 && $1 ne '') { |
2615 |
&perror("WARN", $file, -1, "unless this is a master port, PORTNAME has to be set by \"=\", ". |
2616 |
"not by \"$1=\".") unless ($masterport); |
2617 |
} |
2618 |
if ($tmp !~ /\n(PORTVERSION|DISTVERSION)(.)?=/) { |
2619 |
&perror("FATAL", $file, -1, "PORTVERSION or DISTVERSION has to be there.") unless (($makevar{PORTVERSION} ne '' || $makevar{DISTVERSION} ne '')); |
2620 |
if (!$slaveport && ($makevar{PORTVERSION} ne '' || $makevar{DISTVERSION} ne '')) { |
2621 |
&perror("WARN", $file, -1, "PORTVERSION/DISTVERSION is set externally to this port's Makefile, but this port is not configured as a slave port."); |
2622 |
} |
2623 |
} elsif (defined $2 && $2 ne '') { |
2624 |
&perror("WARN", $file, -1, "unless this is a master port, PORTVERSION has to be set by \"=\", ". |
2625 |
"not by \"$2=\".") unless ($masterport); |
2626 |
} |
2627 |
if ($tmp =~ /\nPORTVERSION.?=/ && $tmp =~ /\nDISTVERSION.?=/) { |
2628 |
&perror("FATAL", $file, -1, "either PORTVERSION or DISTVERSION must be ". |
2629 |
"specified, not both."); |
2630 |
} |
2631 |
if ($newport) { |
2632 |
print "OK: checking for existence of PORTREVISION in new port.\n" |
2633 |
if ($verbose); |
2634 |
if ($tmp =~ /^PORTREVISION(.)?=/m) { |
2635 |
&perror("WARN", $file, -1, "new ports should not set PORTREVISION."); |
2636 |
} |
2637 |
} elsif (!$slaveport) { |
2638 |
print "OK: checking for PORTREVISION=0.\n" if ($verbose); |
2639 |
if ($tmp =~ /^PORTREVISION=\s*0/m) { |
2640 |
&perror("WARN", $file, -1, "Setting PORTREVISION to 0 is not ". |
2641 |
"necessary."); |
2642 |
} |
2643 |
} |
2644 |
if ($newport) { |
2645 |
print "OK: checking for existence of PORTEPOCH in new port.\n" |
2646 |
if ($verbose); |
2647 |
if ($tmp =~ /^PORTEPOCH(.)?=/m) { |
2648 |
&perror("WARN", $file, -1, "new ports should not set PORTEPOCH."); |
2649 |
} |
2650 |
} |
2651 |
print "OK: checking CATEGORIES.\n" if ($verbose); |
2652 |
if ($tmp !~ /\nCATEGORIES(.)?=/) { |
2653 |
&perror("FATAL", $file, -1, "CATEGORIES has to be there.") unless ($makevar{CATEGORIES} ne ''); |
2654 |
if (!$slaveport && $makevar{CATEGORIES} ne '') { |
2655 |
&perror("WARN", $file, -1, "CATEGORIES is set externally to this port's Makefile, but this port is not configured as a slave port."); |
2656 |
} |
2657 |
} elsif (defined $1 && ($i = $1) ne '' && $i =~ /[^?+]/) { |
2658 |
&perror("WARN", $file, -1, "unless this is a master port, CATEGORIES should be set by \"=\", \"?=\", or \"+=\", ". |
2659 |
"not by \"$i=\".") unless ($masterport); |
2660 |
} |
2661 |
|
2662 |
@cat = split(/\s+/, $makevar{CATEGORIES}); |
2663 |
if (@cat == 0) { |
2664 |
&perror("FATAL", $file, -1, "CATEGORIES left blank. set it to \"misc\"". |
2665 |
" if nothing seems apropriate."); |
2666 |
} else { |
2667 |
my %seencat = (); |
2668 |
foreach my $cat (@cat) { |
2669 |
if ($seencat{$cat}) { |
2670 |
&perror("WARN", $file, -1, "Duplicate category, $cat specified". |
2671 |
" in CATEGORIES."); |
2672 |
} else { |
2673 |
$seencat{$cat} = 1; |
2674 |
} |
2675 |
} |
2676 |
} |
2677 |
|
2678 |
if ($use_java && !grep /^java$/, @cat) { |
2679 |
&perror("WARN", $file, -1, "the port uses Java but is not part of the ". |
2680 |
"``java'' category"); |
2681 |
} |
2682 |
|
2683 |
if (scalar(@cat) == 1 && $cat[0] eq "java") { |
2684 |
&perror("FATAL", $file, -1, "the ``java'' category shall not be the only ". |
2685 |
"one for a port"); |
2686 |
} |
2687 |
|
2688 |
if ($newport && scalar(@cat) > 0 && $cat[0] eq "java") { |
2689 |
&perror("WARN", $file, -1, "save for ports directly related to the Java ". |
2690 |
"language, porters are encouraged not to use ``java'' as ". |
2691 |
"the main category for a port"); |
2692 |
} |
2693 |
|
2694 |
if ($committer && $makevar{'.CURDIR'} =~ m/\Q${portsdir}\E\/([^\/]+)\/[^\/]+\/?$/) { |
2695 |
if ($cat[0] ne $1 && $makevar{PKGCATEGORY} ne $1 ) { |
2696 |
&perror("FATAL", $file, -1, "category \"$1\" must be listed first"); |
2697 |
} |
2698 |
} |
2699 |
|
2700 |
#MICHAEL: can these three lang cat checks be combined? |
2701 |
# skip the first category specification if it's a language specific one. |
2702 |
if (grep($_ eq $cat[0], @lang_cat)) { |
2703 |
$has_lang_cat = 1; |
2704 |
$port_lang = $lang_pref{$cat[0]}; |
2705 |
shift @cat; |
2706 |
} |
2707 |
|
2708 |
# skip further if more language specific ones follow. |
2709 |
if (@cat && grep($_ eq $cat[0], @lang_cat)) { |
2710 |
&perror("WARN", $file, -1, "multiple language specific categories detected. ". |
2711 |
"are you sure?"); |
2712 |
do { |
2713 |
shift @cat; |
2714 |
} while (@cat && grep($_ eq $cat[0], @lang_cat)); |
2715 |
} |
2716 |
|
2717 |
# check x11 in CATEGORIES |
2718 |
#MICHAEL: I don't understand this line |
2719 |
if (2 <= @cat && $cat[1] eq "x11") { |
2720 |
&perror("WARN", $file, -1, "only specific kind of apps should ". |
2721 |
"specify \"x11\" in CATEGORIES. ". |
2722 |
"Do you mean just USE_XORG? ". |
2723 |
"Then remove \"x11\" from CATEGORIES."); |
2724 |
} |
2725 |
|
2726 |
if (2 <= @cat) { |
2727 |
# skip the first one that we know is _not_ language specific. |
2728 |
shift @cat; |
2729 |
|
2730 |
# any language specific one after non language specific ones? |
2731 |
foreach my $cat (@cat) { |
2732 |
if (grep($_ eq $cat, @lang_cat)) { |
2733 |
$has_lang_cat = 1; |
2734 |
$port_lang = $lang_pref{$cat}; |
2735 |
&perror("WARN", $file, -1, "when you specify multiple categories, ". |
2736 |
"language specific category should come first."); |
2737 |
} |
2738 |
} |
2739 |
} |
2740 |
|
2741 |
# check the URL |
2742 |
if (($tmp =~ /\nMASTER_SITES[+?]?=[ \t]*([^\n]*)\n/ |
2743 |
&& $1 !~ /^[ \t]*$/) || ($makevar{MASTER_SITES} ne '')) { |
2744 |
print "OK: seen MASTER_SITES, sanity checking URLs.\n" |
2745 |
if ($verbose); |
2746 |
my $urlseen = 0; |
2747 |
my @sites = split(/\s+/, $1 // ''); |
2748 |
my $ftphttp = 0; |
2749 |
foreach my $i (@sites) { |
2750 |
last if ($i =~ /^#/); |
2751 |
if ($i =~ m#^\w+://#) { |
2752 |
$urlseen = 1; |
2753 |
$ftphttp = 1 if ($i =~ /^(ftp|http):/); |
2754 |
&urlcheck($i, $file); |
2755 |
unless (&is_predefined($i, $file)) { |
2756 |
print "OK: URL \"$i\" ok.\n" |
2757 |
if ($verbose); |
2758 |
} |
2759 |
} else { |
2760 |
my $good_ms = 1; |
2761 |
foreach my $mss (split(/\s+/, $makevar{MASTER_SITES_SUBDIRS})) { |
2762 |
my ($ms, $sd) = split(/:/, $mss); |
2763 |
if ($i =~ /^$ms/ && $i ne $ms) { |
2764 |
my $ip = $i; |
2765 |
$ip =~ s/^$ms\///; |
2766 |
my $exp_sd = get_makevar($ip); |
2767 |
if ($exp_sd eq $sd) { |
2768 |
&perror("WARN", $file, -1, "typically when you specify magic site $ms ". |
2769 |
"you do not need anything else as $sd is assumed"); |
2770 |
$good_ms = 0; |
2771 |
} |
2772 |
} |
2773 |
} |
2774 |
if ($good_ms) { |
2775 |
print "OK: non-URL \"$i\" ok.\n" |
2776 |
if ($verbose); |
2777 |
} |
2778 |
# Assume variables contain an ftp/http site. |
2779 |
$ftphttp = 1; |
2780 |
} |
2781 |
} |
2782 |
} else { |
2783 |
&perror("WARN", $file, -1, "no MASTER_SITES found. is it ok?"); |
2784 |
} |
2785 |
|
2786 |
# check DISTFILES and related items. |
2787 |
$distfiles = $1 if ($tmp =~ /\nDISTFILES[+?]?=[ \t]*([^\n]+)\n/); |
2788 |
$portname = $makevar{PORTNAME}; |
2789 |
$portversion = $makevar{PORTVERSION}; |
2790 |
$distversionprefix = $makevar{DISTVERSIONPREFIX}; |
2791 |
$distversion = $makevar{DISTVERSION}; |
2792 |
$distversionsuffix = $makevar{DISTVERSIONSUFFIX}; |
2793 |
$distname = $1 if ($tmp =~ /\nDISTNAME[+?]?=[ \t]*([^\n]+)\n/); |
2794 |
$extractsufx = $1 if ($tmp =~ /\nEXTRACT_SUFX[+?]?=[ \t]*([^\n]+)\n/); |
2795 |
|
2796 |
# check bogus EXTRACT_SUFX. |
2797 |
if ($extractsufx ne '') { |
2798 |
print "OK: seen EXTRACT_SUFX, checking value.\n" if ($verbose); |
2799 |
if ($distfiles ne '') { |
2800 |
&perror("WARN", $file, -1, "no need to define EXTRACT_SUFX if ". |
2801 |
"DISTFILES is defined."); |
2802 |
} |
2803 |
if ($extractsufx eq '.tar.gz') { |
2804 |
&perror("WARN", $file, -1, "EXTRACT_SUFX is \".tar.gz.\" ". |
2805 |
"by default. you don't need to specify it."); |
2806 |
} |
2807 |
if ($extractsufx =~ /^\.tar\.(bz2|lzma|xz|Z)$/) { |
2808 |
my $ext = $1; |
2809 |
$ext = 'bzip2' if ($ext eq 'bz2'); |
2810 |
&perror("WARN", $file, -1, "EXTRACT_SUFX is \".tar.$ext\". ". |
2811 |
"Please use USES=tar:$ext instead."); |
2812 |
} |
2813 |
if ($extractsufx =~ /^\.(tgz|tbz|txz)$/) { |
2814 |
&perror("WARN", $file, -1, "EXTRACT_SUFX is \".$1\". ". |
2815 |
"Please use USES=tar:$1 instead."); |
2816 |
} |
2817 |
if ($extractsufx eq '.zip') { |
2818 |
&perror("WARN", $file, -1, "EXTRACT_SUFX is \".zip\" ". |
2819 |
"You should use USES[+]=zip instead."); |
2820 |
} |
2821 |
} else { |
2822 |
print "OK: no EXTRACT_SUFX seen, using default value.\n" |
2823 |
if ($verbose); |
2824 |
$extractsufx = '.tar.gz'; |
2825 |
} |
2826 |
|
2827 |
print "OK: sanity checking PORTNAME/PORTVERSION/DISTVERSIONPREFIX/DISTVERSION/DISTVERSIONSUFFIX.\n" if ($verbose); |
2828 |
if ($distname ne '') { |
2829 |
my $exp_distname = $makevar{DISTNAME}; |
2830 |
if ($exp_distname eq "$portname-$portversion") { |
2831 |
&perror("WARN", $file, -1, "DISTNAME is \${PORTNAME}-\${PORTVERSION} by ". |
2832 |
"default, you don't need to define DISTNAME."); |
2833 |
} else { |
2834 |
if ($exp_distname eq "$portname-$distversionprefix$distversion$distversionsuffix") { |
2835 |
&perror("WARN", $file, -1, "DISTNAME is \${PORTNAME}-\${DISTVERSIONPREFIX}\${DISTVERSION}\${DISTVERSIONSUFFIX} by ". |
2836 |
"default, you don't need to define DISTNAME."); |
2837 |
} |
2838 |
} |
2839 |
if ($distname =~ /PORTREVISION/) { |
2840 |
&perror("FATAL", $file, -1, "DISTNAME contains a reference to ". |
2841 |
"PORTREVISION. You should only be using PORTVERSION"); |
2842 |
} |
2843 |
if ($distname =~ /PORTEPOCH/) { |
2844 |
&perror("FATAL", $file, -1, "DISTNAME contains a reference to ". |
2845 |
"PORTEPOCH. You should only be using PORTVERSION"); |
2846 |
} |
2847 |
} |
2848 |
if ($portname =~ /^$re_lang_short/) { |
2849 |
&perror("FATAL", $file, -1, "language prefix is automatically". |
2850 |
" set by PKGNAMEPREFIX.". |
2851 |
" you must remove it from PORTNAME."); |
2852 |
} |
2853 |
if ($portname =~ /([|<>=! ])/) { |
2854 |
&perror("FATAL", $file, -1, "PORTNAME contains the illegal character \"$1\".". |
2855 |
" You should modify \"$portname\"."); |
2856 |
} elsif ($portname =~ /\$[\{\(].+[\}\)]/) { |
2857 |
&perror("WARN", $file, -1, "using variable in PORTNAME.". |
2858 |
" consider using PKGNAMEPREFIX and/or PKGNAMESUFFIX."); |
2859 |
} elsif ($portname =~ /([^\w._@+-])/) { |
2860 |
&perror("WARN", $file, -1, "using \"$1\" in PORTNAME.". |
2861 |
" You should modify \"$portname\"."); |
2862 |
} elsif ($portname =~ /-/ && $distname ne '') { |
2863 |
&perror("WARN", $file, -1, "using hyphen in PORTNAME.". |
2864 |
" consider using PKGNAMEPREFIX and/or PKGNAMESUFFIX."); |
2865 |
} |
2866 |
if ($portversion eq '' && $distversion eq '') { |
2867 |
&perror("FATAL", $file, -1, "either PORTVERSION or DISTVERSION must be specified"); |
2868 |
} |
2869 |
if ($portversion =~ /^pl[0-9]*$/ |
2870 |
|| $portversion =~ /^[0-9]*[A-Za-z]?[0-9]*(\.[0-9]*[A-Za-z]?[0-9+]*)*$/) { |
2871 |
print "OK: PORTVERSION \"$portversion\" looks fine.\n" if ($verbose); |
2872 |
} elsif ($portversion =~ /^[^\-]*\$[{\(].+[\)}][^\-]*$/) { |
2873 |
&perror("WARN", $file, -1, "using variable, \"$portversion\", as version ". |
2874 |
"number"); |
2875 |
} elsif ($portversion =~ /([-,_<>=! #*])/) { |
2876 |
&perror("FATAL", $file, -1, "PORTVERSION must not contain \"$1\". ". |
2877 |
"You should modify \"$portversion\"."); |
2878 |
} else { |
2879 |
&perror("FATAL", $file, -1, "PORTVERSION looks illegal. ". |
2880 |
"You should modify \"$portversion\"."); |
2881 |
|
2882 |
} |
2883 |
|
2884 |
$pkg_version = $makevar{PKG_VERSION}; |
2885 |
|
2886 |
if ($makevar{CONFLICTS}) { |
2887 |
print "OK: checking CONFLICTS.\n" if ($verbose); |
2888 |
foreach my $conflict (split ' ', $makevar{CONFLICTS}) { |
2889 |
`$pkg_version -T '$makevar{PKGNAME}' '$conflict'`; |
2890 |
my $selfconflict = !$?; |
2891 |
if ($selfconflict) { |
2892 |
&perror("FATAL", "", -1, "Package conflicts with itself. ". |
2893 |
"You should remove \"$conflict\" from CONFLICTS."); |
2894 |
} |
2895 |
} |
2896 |
} |
2897 |
|
2898 |
$versiondir = $ENV{VERSIONDIR} // '/var/db/chkversion'; |
2899 |
|
2900 |
$versionfile = "$versiondir/VERSIONS"; |
2901 |
$useindex = !-r "$versionfile"; |
2902 |
|
2903 |
$versionfile = "$portsdir/$makevar{INDEXFILE}" |
2904 |
if $useindex; |
2905 |
|
2906 |
if (-r "$versionfile") { |
2907 |
print "OK: checking if PORTVERSION is going backwards.\n" if ($verbose); |
2908 |
open VERSIONS, "<$versionfile"; |
2909 |
|
2910 |
while (<VERSIONS>) { |
2911 |
my($origin, $version) = ('', ''); |
2912 |
chomp; |
2913 |
next if /^(#|$)/; |
2914 |
if ($useindex) { |
2915 |
($version, $origin) = split /\|/; |
2916 |
$origin =~ s,^.*/([^/]+/[^/]+)/?$,$1,; |
2917 |
} else { |
2918 |
($origin, $version) = split; |
2919 |
} |
2920 |
if ($origin eq $makevar{PKGORIGIN}) { |
2921 |
my $newversion = $makevar{PKGNAME}; |
2922 |
my $oldversion = $version; |
2923 |
my $result = ''; |
2924 |
|
2925 |
$newversion =~ s/^.*-//; |
2926 |
$oldversion =~ s/^.*-//; |
2927 |
|
2928 |
$result = `$pkg_version -t '$newversion' '$oldversion'`; |
2929 |
chomp $result; |
2930 |
if ($result eq '<') { |
2931 |
&perror("FATAL", $file, -1, "$makevar{PKGNAME} < $version. ". |
2932 |
"Choose another PORTVERSION or bump PORTEPOCH."); |
2933 |
# $backwards{$origin} = "$pkgname{$origin} < $version"; |
2934 |
} |
2935 |
last; |
2936 |
} |
2937 |
} |
2938 |
close VERSIONS; |
2939 |
} |
2940 |
|
2941 |
# if DISTFILES have only single item, it is better to avoid DISTFILES |
2942 |
# and to use combination of DISTNAME and EXTRACT_SUFX. |
2943 |
# example: |
2944 |
# DISTFILES=package-1.0.tgz |
2945 |
# should be |
2946 |
# DISTNAME= package-1.0 |
2947 |
# EXTRACT_SUFX= .tgz |
2948 |
if ($distfiles =~ /^\S+$/ && $distfiles !~ /:[^\/:]+$/) { |
2949 |
$bogusdistfiles++; |
2950 |
print "OK: seen DISTFILES with single item, checking value.\n" |
2951 |
if ($verbose); |
2952 |
&perror("WARN", $file, -1, "use of DISTFILES with single file ". |
2953 |
"discouraged. distribution filename should be set by ". |
2954 |
"DISTNAME and EXTRACT_SUFX."); |
2955 |
if ($distfiles eq (($distname ne '') ? $distname : "$portname-$portversion") . $extractsufx) { |
2956 |
&perror("WARN", $file, -1, "definition of DISTFILES not necessary. ". |
2957 |
"DISTFILES is \${DISTNAME}/\${EXTRACT_SUFX} ". |
2958 |
"by default."); |
2959 |
} |
2960 |
|
2961 |
# display advice only in certain cases. |
2962 |
#MICHAEL: will this work with multiple distfiles in this list? what about |
2963 |
# doing the same sort of thing for DISTNAME, is it needed? |
2964 |
if ($distfiles =~ /^\Q$i\E([\-.].+)$/) { |
2965 |
&perror("WARN", $file, -1, "how about \"EXTRACT_SUFX=$1\"". |
2966 |
", instead of DISTFILES?"); |
2967 |
} |
2968 |
} |
2969 |
|
2970 |
push(@varnames, qw( |
2971 |
PORTNAME PORTVERSION DISTVERSIONPREFIX DISTVERSION DISTVERSIONSUFFIX |
2972 |
PORTREVISION PORTEPOCH CATEGORIES MASTER_SITES MASTER_SITE_SUBDIR |
2973 |
PROJECTHOST PKGNAMEPREFIX PKGNAMESUFFIX DISTNAME EXTRACT_SUFX DISTFILES |
2974 |
DIST_SUBDIR EXTRACT_ONLY |
2975 |
)); |
2976 |
|
2977 |
# |
2978 |
# section 3: PATCH_SITES/PATCHFILES(optional) |
2979 |
# |
2980 |
print "OK: checking second section of $file (PATCH*: optional).\n" |
2981 |
if ($verbose); |
2982 |
$tmp = $sections[$idx] // ''; |
2983 |
|
2984 |
if ($tmp =~ /(PATCH_SITES|PATCH_SITE_SUBDIR|PATCHFILES|PATCH_DIST_STRIP)/) { |
2985 |
&checkearlier($file, $tmp, @varnames); |
2986 |
|
2987 |
if ($tmp =~ /PATCH_SITES[?+]?=[^\n]+\n/) { |
2988 |
print "OK: seen PATCH_SITES.\n" if ($verbose); |
2989 |
$tmp =~ s/PATCH_SITES[?+]?=[^\n]+\n//; |
2990 |
} |
2991 |
if ($tmp =~ /PATCH_SITE_SUBDIR[?+]?=[^\n]+\n/) { |
2992 |
print "OK: seen PATCH_SITE_SUBDIR.\n" if ($verbose); |
2993 |
$tmp =~ s/PATCH_SITE_SUBDIR[?+]?=[^\n]+\n//; |
2994 |
} |
2995 |
if ($tmp =~ /PATCHFILES[?+]?=[^\n]+\n/) { |
2996 |
print "OK: seen PATCHFILES.\n" if ($verbose); |
2997 |
$tmp =~ s/PATCHFILES[?+]?=[^\n]+\n//; |
2998 |
} |
2999 |
if ($tmp =~ /PATCH_DIST_STRIP[?+]?=[^\n]+\n/) { |
3000 |
print "OK: seen PATCH_DIST_STRIP.\n" if ($verbose); |
3001 |
$tmp =~ s/PATCH_DIST_STRIP[?+]?=[^\n]+\n//; |
3002 |
} |
3003 |
|
3004 |
&checkextra($tmp, 'PATCH_SITES', $file); |
3005 |
|
3006 |
$idx++; |
3007 |
} |
3008 |
|
3009 |
push(@varnames, qw( |
3010 |
PATCH_SITES PATCHFILES PATCH_DIST_STRIP |
3011 |
)); |
3012 |
|
3013 |
# |
3014 |
# section 4: MAINTAINER |
3015 |
# |
3016 |
print "OK: checking third section of $file (MAINTAINER).\n" |
3017 |
if ($verbose); |
3018 |
$tmp = $sections[$idx] // ''; |
3019 |
|
3020 |
&checkearlier($file, $tmp, @varnames); |
3021 |
&checkorder('MAINTAINER', $tmp, $file, qw( |
3022 |
MAINTAINER COMMENT |
3023 |
)); |
3024 |
|
3025 |
$tmp = "\n" . $tmp; |
3026 |
if ($tmp =~ /\nMAINTAINER(\?)?=([^\n]+)/) { |
3027 |
my $addr = $2; |
3028 |
if (defined $1 && $1 ne '') { |
3029 |
&perror("WARN", $file, -1, "unless this is a master port, ". |
3030 |
"MAINTAINER has to be set by \"=\", ". |
3031 |
"not by \"$1=\".") unless ($masterport); |
3032 |
} |
3033 |
$addr =~ s/^\s*//; |
3034 |
$addr =~ s/\s*$//; |
3035 |
if ($addr =~ /[\s,<>()]/) { |
3036 |
&perror("FATAL", $file, -1, "MAINTAINER should be a single address without comment."); |
3037 |
} |
3038 |
if ($addr !~ /^[^\@]+\@[\w\d\-\.]+$/) { |
3039 |
&perror("FATAL", $file, -1, "MAINTAINER address, $addr, does not appear to be a valid email address."); |
3040 |
} |
3041 |
if ($newport && $addr =~ /ports\@freebsd.org/i) { |
3042 |
&perror("WARN", $file, -1, "new ports should not be maintained by ". |
3043 |
"ports\@FreeBSD.org."); |
3044 |
} |
3045 |
$tmp =~ s/\nMAINTAINER\??=[^\n]+//; |
3046 |
} elsif ($whole !~ /\nMAINTAINER[?]?=/) { |
3047 |
&perror("FATAL", $file, -1, "no MAINTAINER listed.") unless ($makevar{MAINTAINER} ne ''); |
3048 |
if (!$slaveport && $makevar{MAINTAINER} ne '') { |
3049 |
&perror("WARN", $file, -1, "MAINTAINER is set externally to this port's Makefile, but this port is not configured as a slave port."); |
3050 |
} |
3051 |
} |
3052 |
$tmp =~ s/\n\n+/\n/g; |
3053 |
|
3054 |
# check COMMENT |
3055 |
if ($tmp !~ /\nCOMMENT(.)?=/) { |
3056 |
&perror("FATAL", $file, -1, "COMMENT has to be there.") unless ($makevar{COMMENT} ne ''); |
3057 |
if (!$slaveport && $makevar{COMMENT} ne '') { |
3058 |
&perror("WARN", $file, -1, "COMMENT is set externally to this port's Makefile, but this port is not configured as a slave port."); |
3059 |
} |
3060 |
} elsif (defined $1 && $1 ne '') { |
3061 |
&perror("WARN", $file, -1, "unless this is a master port, COMMENT has to be set by \"=\", ". |
3062 |
"not by \"$1=\".") unless ($masterport); |
3063 |
} else { # check for correctness |
3064 |
if (($makevar{COMMENT} !~ /^["\[0-9A-Z]/) || ($makevar{COMMENT} =~ m/\.$/)) { #" |
3065 |
&perror("WARN", $file, -1, "COMMENT should begin with a capital, and end without a period"); |
3066 |
} |
3067 |
if (length($makevar{COMMENT}) > 70) { |
3068 |
&perror("WARN", $file, -1, "COMMENT exceeds 70 characters limit."); |
3069 |
} |
3070 |
} |
3071 |
|
3072 |
$idx++; |
3073 |
|
3074 |
push(@varnames, qw( |
3075 |
MAINTAINER COMMENT |
3076 |
)); |
3077 |
|
3078 |
# |
3079 |
# section 5: LICENSE |
3080 |
# |
3081 |
print "OK: checking fourth section of $file (LICENSE).\n" |
3082 |
if ($verbose); |
3083 |
$tmp = $sections[$idx] // ''; |
3084 |
|
3085 |
if ($makevar{LICENSE}) { |
3086 |
&checkorder('LICENSE', $tmp, $file, qw( |
3087 |
LICENSE LICENSE_COMB LICENSE_GROUPS(_\w+)? LICENSE_NAME(_\w+)? |
3088 |
LICENSE_TEXT(_\w+)? LICENSE_FILE(_\w+)? LICENSE_PERMS(_\w+)? |
3089 |
LICENSE_DISTFILES(_\w+)? |
3090 |
)); |
3091 |
|
3092 |
# check LICENSE |
3093 |
if ($makevar{LICENSE} && $makevar{LICENSE} ne '') { |
3094 |
my $comb = $makevar{LICENSE_COMB} // 'single'; |
3095 |
|
3096 |
my @tokens = split(/ /, $makevar{LICENSE}); |
3097 |
if ($comb eq 'single' && scalar(@tokens) > 1) { |
3098 |
&perror("FATAL", $file, -1, "LICENSE contains multiple licenses but LICENSE_COMB is not set to 'dual' or 'multi'"); |
3099 |
} |
3100 |
} |
3101 |
|
3102 |
# check value of LICENSE_COMB |
3103 |
if ($makevar{LICENSE_COMB} && $makevar{LICENSE_COMB} !~ /^(single|dual|multi$)/) { |
3104 |
&perror("FATAL", $file, -1, "LICENSE_COMB contains invalid value '$1' - must be one of 'single', 'dual', 'multi'"); |
3105 |
} |
3106 |
|
3107 |
$idx++; |
3108 |
|
3109 |
push(@varnames, qw( |
3110 |
LICENSE LICENSE_COMB LICENSE_GROUPS LICENSE_NAME |
3111 |
LICENSE_TEXT LICENSE_FILE LICENSE_PERMS |
3112 |
)); |
3113 |
} else { |
3114 |
&perror("WARN", $file, -1, "Consider defining LICENSE."); |
3115 |
} |
3116 |
|
3117 |
# |
3118 |
# section 6: BROKEN/IGNORE/DEPRECATED (may not be there) |
3119 |
# |
3120 |
print "OK: checking sixth section of $file (BROKEN/IGNORE/DEPRECATED).\n" |
3121 |
if ($verbose); |
3122 |
$tmp = $sections[$idx] // ''; |
3123 |
|
3124 |
@linestocheck = qw( |
3125 |
DEPRECATED EXPIRATION_DATE FORBIDDEN BROKEN(_\w+)? IGNORE(_\w+)? |
3126 |
ONLY_FOR_ARCHS ONLY_FOR_ARCHS_REASON(_\w+)? |
3127 |
NOT_FOR_ARCHS NOT_FOR_ARCHS_REASON(_\w+)? |
3128 |
); |
3129 |
|
3130 |
my $brokenpattern = "^(" . join("|", @linestocheck) . ")[?+:]?="; |
3131 |
|
3132 |
if ($tmp =~ /$brokenpattern/) { |
3133 |
$idx++; |
3134 |
} |
3135 |
|
3136 |
foreach my $i (@linestocheck) { |
3137 |
$tmp =~ s/$i[?+:]?=[^\n]+\n//g; |
3138 |
} |
3139 |
|
3140 |
push(@varnames, @linestocheck); |
3141 |
&checkearlier($file, $tmp, @varnames); |
3142 |
|
3143 |
# |
3144 |
# section 7: *_DEPENDS (may not be there) |
3145 |
# |
3146 |
print "OK: checking seventh section of $file (*_DEPENDS).\n" |
3147 |
if ($verbose); |
3148 |
$tmp = $sections[$idx] // ''; |
3149 |
|
3150 |
# Check for direct assignment of BUILD_DEPENDS to RUN_DEPENDS. |
3151 |
if ($tmp =~ /\nRUN_DEPENDS=[ \t]*\$\{BUILD_DEPENDS}/) { |
3152 |
&perror("FATAL", $file, -1, "RUN_DEPENDS should not be set to ". |
3153 |
"\${BUILD_DEPENDS} as \${BUILD_DEPENDS} includes other ". |
3154 |
"implicit dependencies. Instead, copy the explicit dependencies ". |
3155 |
"from BUILD_DEPENDS to RUN_DEPENDS. See ". |
3156 |
"http://www.freebsd.org/doc/en_US.ISO8859-1/books/porters-handbook/makefile-depend.html#AEN2154 ". |
3157 |
"for more details."); |
3158 |
} |
3159 |
|
3160 |
@linestocheck = qw( |
3161 |
EXTRACT_DEPENDS LIB_DEPENDS PATCH_DEPENDS BUILD_DEPENDS RUN_DEPENDS |
3162 |
TEST_DEPENDS FETCH_DEPENDS DEPENDS_TARGET |
3163 |
); |
3164 |
|
3165 |
if ($tmp =~ /^(PATCH_|EXTRACT_|LIB_|BUILD_|RUN_|TEST_|FETCH_)DEPENDS/m) { |
3166 |
&checkearlier($file, $tmp, @varnames); |
3167 |
|
3168 |
check_depends_syntax($tmp, $file); |
3169 |
|
3170 |
foreach my $i (@linestocheck) { |
3171 |
foreach my $flavor (split(/\s+/, $makevar{FLAVORS} // '')) { |
3172 |
$tmp =~ s/${flavor}_$i[?+:]?=[^\n]+\n//g; |
3173 |
} |
3174 |
$tmp =~ s/$i[?+:]?=[^\n]+\n//g; |
3175 |
} |
3176 |
|
3177 |
# Remove any other *_DEPENDS lines as people may |
3178 |
# use a macro for common depends as described in |
3179 |
# section 5.9.2 of the Porter's Handbook. |
3180 |
$tmp =~ s/.+_DEPENDS[?+:]?=[^\n]+\n//g; |
3181 |
|
3182 |
&checkextra($tmp, '*_DEPENDS', $file); |
3183 |
|
3184 |
$idx++; |
3185 |
} |
3186 |
|
3187 |
push(@varnames, @linestocheck); |
3188 |
&checkearlier($file, $tmp, @varnames); |
3189 |
|
3190 |
# |
3191 |
# Makefile 7: check the rest of file |
3192 |
# |
3193 |
print "OK: checking the rest of the $file.\n" if ($verbose); |
3194 |
$tmp = join("\n\n", @sections[$idx .. scalar(@sections)-1]); |
3195 |
|
3196 |
$tmp = "\n" . $tmp; # to make the begin-of-line check easier |
3197 |
|
3198 |
&checkearlier($file, $tmp, @varnames); |
3199 |
|
3200 |
# Check depends that might be specified based on the WITH_/WITHOUT_ |
3201 |
# arguments and other external variables. |
3202 |
check_depends_syntax($tmp, $file); |
3203 |
|
3204 |
# check WRKSRC/NO_WRKSUBDIR |
3205 |
# |
3206 |
# do not use DISTFILES/DISTNAME to control over WRKSRC. |
3207 |
# DISTNAME is for controlling distribution filename. |
3208 |
# example: |
3209 |
# DISTNAME= package |
3210 |
# DISTFILES=package-1.0.tgz |
3211 |
# should be |
3212 |
# DISTNAME= package-1.0 |
3213 |
# EXTRACT_SUFX=.tgz |
3214 |
# WRKSRC= ${WRKDIR}/package |
3215 |
# |
3216 |
print "OK: checking WRKSRC.\n" if ($verbose); |
3217 |
$wrksrc = $nowrksubdir = ''; |
3218 |
$wrksrc = $1 if ($tmp =~ /\nWRKSRC[+?]?=[ \t]*([^\n]*)\n/); |
3219 |
$nowrksubdir = $1 if ($tmp =~ /\nNO_WRKSUBDIR[+?]?=[ \t]*([^\n]*)\n/); |
3220 |
if ($nowrksubdir eq '') { |
3221 |
$realwrksrc = $wrksrc ? "$wrksrc/$distname" |
3222 |
: "\${WRKDIR}/$distname"; |
3223 |
} else { |
3224 |
$realwrksrc = $wrksrc ? $wrksrc : '${WRKDIR}'; |
3225 |
} |
3226 |
print "OK: WRKSRC seems to be $realwrksrc.\n" if ($verbose); |
3227 |
|
3228 |
if ($nowrksubdir eq '') { |
3229 |
print "OK: no NO_WRKSUBDIR, checking value of WRKSRC.\n" |
3230 |
if ($verbose); |
3231 |
if ($wrksrc eq 'work' || $wrksrc =~ /^$[\{\(]WRKDIR[\}\)]/) { |
3232 |
&perror("WARN", $file, -1, "WRKSRC is set to meaningless value ". |
3233 |
"\"$1\".". |
3234 |
($nowrksubdir eq '' |
3235 |
? " use \"NO_WRKSUBDIR=yes\" instead." |
3236 |
: "")); |
3237 |
} |
3238 |
if ($bogusdistfiles) { |
3239 |
if ($distname ne '' && $wrksrc eq '') { |
3240 |
&perror("WARN", $file, -1, "do not use DISTFILES and DISTNAME ". |
3241 |
"to control WRKSRC. how about ". |
3242 |
"\"WRKSRC=\${WRKDIR}/$distname\"?"); |
3243 |
} else { |
3244 |
&perror("WARN", $file, -1, "DISTFILES/DISTNAME affects WRKSRC. ". |
3245 |
"take caution when changing them."); |
3246 |
} |
3247 |
} |
3248 |
} else { |
3249 |
print "OK: seen NO_WRKSUBDIR, checking value of WRKSRC.\n" |
3250 |
if ($verbose); |
3251 |
if ($wrksrc eq 'work' || $wrksrc =~ /^$[\{\(]WRKDIR[\}\)]/) { |
3252 |
&perror("WARN", $file, -1, "definition of WRKSRC not necessary. ". |
3253 |
"WRKSRC is \${WRKDIR} by default."); |
3254 |
} |
3255 |
} |
3256 |
|
3257 |
# check RESTRICTED/NO_CDROM/NO_PACKAGE |
3258 |
print "OK: checking RESTRICTED/NO_CDROM/NO_PACKAGE.\n" if ($verbose); |
3259 |
if ($committer && $tmp =~ /\n(RESTRICTED|NO_CDROM|NO_PACKAGE)[+?]?=/) { |
3260 |
&perror("WARN", $file, -1, "\"$1\" found. do not forget to update ". |
3261 |
"ports/LEGAL."); |
3262 |
} |
3263 |
|
3264 |
# check NO_STAGE |
3265 |
if ($makevar{NO_STAGE}) { |
3266 |
&perror("FATAL", $file, -1, "STAGE support is missing."); |
3267 |
} |
3268 |
|
3269 |
# various MAN'uals related checks |
3270 |
if ($makevar{USE_PERL5} =~ /\b(configure|modbuild|modbuildtiny)\b/ |
3271 |
&& $tmp =~ /\nMAN3PREFIX=\s*\$\{PREFIX}\/lib\/perl5\/\$\{PERL_VER/) { |
3272 |
&perror("WARN", $file, -1, "MAN3PREFIX is ". |
3273 |
"\"\${PREFIX}/lib/perl5/\${PERL_VERSION}\" ". |
3274 |
"when USE_PERL5=configure|modbuild|modbuildtiny is set. You do not need to specify it."); |
3275 |
} |
3276 |
|
3277 |
if ($tmp =~ /\nMAN[1-9LN][?]?=/) { |
3278 |
&perror("FATAL", $file, -1, "MAN[1-9LN] macro is not supported anymore. ". |
3279 |
"Please list manpages in plist."); |
3280 |
} |
3281 |
|
3282 |
# check INFO |
3283 |
print "OK: checking INFO.\n" if ($verbose); |
3284 |
if ($tmp =~ /\nINFO=\s*([^\n]*)\n/) { |
3285 |
my @minfo = grep($_ !~ /^\s*$/, split(/\s+/, $1)); |
3286 |
if ($tmp =~ /[\/|\s]install-info\s/) { |
3287 |
&perror("FATAL", $file, -1, "install-info is automatically run ". |
3288 |
"when INFO is defined."); |
3289 |
} |
3290 |
foreach $i (@minfo) { |
3291 |
if ($i =~ /\.info(-\d+)?$/) { |
3292 |
&perror("FATAL", $file, -1, "do not include the .info extension ". |
3293 |
"on files listed in the INFO macro."); |
3294 |
} |
3295 |
} |
3296 |
} elsif ($tmp =~ /[\/|\s]install-info\s/) { |
3297 |
&perror("WARN", $file, -1, "do not call install-info directly. Use the ". |
3298 |
"INFO macro instead."); |
3299 |
} |
3300 |
|
3301 |
# check for HAS_CONFIGURE or GNU_CONFIGURE |
3302 |
if ($tmp =~ /\nGNU_CONFIGURE[?+]?=/ |
3303 |
&& $tmp =~ /\n(HAS_CONFIGURE)[?+]?=/) { |
3304 |
&perror("WARN", $file, -1, "since you already have GNU_CONFIGURE, ". |
3305 |
"you do not need $1."); |
3306 |
} |
3307 |
|
3308 |
# check direct use of important make targets. |
3309 |
if ($tmp =~ /\n(fetch|extract|patch|configure|build|install):/) { |
3310 |
&perror("FATAL", $file, -1, "direct redefinition of make target \"$1\" ". |
3311 |
"discouraged. redefine \"do-$1\" instead."); |
3312 |
} |
3313 |
|
3314 |
# check for incorrect use of the pre-everything target. |
3315 |
if ($tmp =~ /\npre-everything:[^:]/) { |
3316 |
&perror("FATAL", $file, -1, "use pre-everything:: instead of pre-everything:"); |
3317 |
} |
3318 |
|
3319 |
if ($tmp =~ /^pre-patch:/m && $use_gnome_hack) { |
3320 |
&perror("FATAL", $file, -1, "pre-patch target overwrites gnomehack component. ". |
3321 |
"use post-patch instead."); |
3322 |
} |
3323 |
|
3324 |
if ($tmp =~ /^do-build:/m && $use_ant) { |
3325 |
&perror("WARN", $file, -1, "USE_ANT is intended only for ports that ". |
3326 |
"build with Ant. It is recommended not to override the default ". |
3327 |
"'do-build:' target when defining USE_ANT"); |
3328 |
} |
3329 |
|
3330 |
# |
3331 |
# check for deprecated use of USE_RC_SUBR, and current syntax |
3332 |
# |
3333 |
if ($tmp =~ /\nUSE_RC_SUBR=([\s]*)(.*)/) { |
3334 |
my $subr_value = $makevar{USE_RC_SUBR}; |
3335 |
if ($subr_value eq '') { |
3336 |
$subr_value = $2; |
3337 |
} |
3338 |
|
3339 |
if (($subr_value =~ /^yes$/i) || |
3340 |
($subr_value =~ /^true$/i) || |
3341 |
($subr_value =~ /^1$/)) { |
3342 |
&perror("FATAL", $file, -1, "The value of the USE_RC_SUBR variable ". |
3343 |
"should be the name of the intended rc.d script, and there ". |
3344 |
"should be a corresponding file in the files/ directory."); |
3345 |
} else { |
3346 |
foreach my $i (split(/\s/, $subr_value)) { |
3347 |
if ($i ne '' && -f "files/$i.in") { |
3348 |
if (open(RCIN, "< files/$i.in")) { |
3349 |
my @rccontents = <RCIN>; |
3350 |
my $found_provide = 0; |
3351 |
foreach my $line (@rccontents) { |
3352 |
if ($line =~ /^# PROVIDE:/) { |
3353 |
$found_provide = 1; |
3354 |
last; |
3355 |
} |
3356 |
} |
3357 |
if (!$found_provide) { |
3358 |
&perror("FATAL", "files/$i.in", -1, "rc.d script ". |
3359 |
"$i.in must contain a '# PROVIDE:' line in ". |
3360 |
"order to be started at boot time."); |
3361 |
} |
3362 |
|
3363 |
close(RCIN); |
3364 |
} |
3365 |
} |
3366 |
} |
3367 |
} |
3368 |
} |
3369 |
|
3370 |
# check for health of SUB_FILES |
3371 |
|
3372 |
if ($tmp =~ /\nSUB_FILES=([\s]*)(.*)/) { |
3373 |
my $subr_value = $makevar{SUB_FILES}; |
3374 |
if ($subr_value eq '') { |
3375 |
$subr_value = $2; |
3376 |
} |
3377 |
foreach my $i (split(/\s/, $subr_value)) { |
3378 |
my $mvar; |
3379 |
if ($i =~ /\$\{([^}]+)\}/) { |
3380 |
$mvar = $1; |
3381 |
if (defined($makevar{$mvar})) { |
3382 |
$i = $makevar{$mvar}; |
3383 |
} else { |
3384 |
$i = &get_makevar($mvar); |
3385 |
} |
3386 |
} |
3387 |
if ($i ne '' && ! -f "files/$i.in") { |
3388 |
&perror("FATAL", $file, -1, "$i listed in SUB_FILES/USE_RC_SUBR, ". |
3389 |
"but files/$i.in is missing."); |
3390 |
} elsif ($i eq '' && $mvar && $mvar ne '') { |
3391 |
&perror("WARN", $file, -1, "possible undefined make variable ". |
3392 |
"$mvar used as the value for SUB_FILES/USE_RC_SUBR."); |
3393 |
} |
3394 |
} |
3395 |
} |
3396 |
|
3397 |
1; |
3398 |
} |
3399 |
|
3400 |
sub perror($$$$) { |
3401 |
my($type, $file, $line, $msg) = @_; |
3402 |
|
3403 |
if ($type eq 'FATAL') { |
3404 |
$err++; |
3405 |
} else { |
3406 |
$warn++; |
3407 |
} |
3408 |
if ($grouperrs) { |
3409 |
$msg = '%%LINES%%' . $msg; |
3410 |
if ($file ne "") { |
3411 |
$msg = $file . ": " . $msg; |
3412 |
} |
3413 |
$msg = $type . ": " . $msg; |
3414 |
if (!$errcache{$msg}) { |
3415 |
push @errlst, $msg; |
3416 |
} |
3417 |
if ($line > -1) { |
3418 |
push @{$errcache{$msg}}, $line; |
3419 |
} |
3420 |
} else { |
3421 |
if ($line > -1) { |
3422 |
$msg = "[$line]: " . $msg; |
3423 |
} |
3424 |
if ($file ne "") { |
3425 |
$msg = $file . ": " . $msg; |
3426 |
} |
3427 |
$msg = $type . ": " . $msg; |
3428 |
print $msg . "\n"; |
3429 |
} |
3430 |
} |
3431 |
|
3432 |
sub checkextra { |
3433 |
my($str, $section, $file) = @_; |
3434 |
|
3435 |
$str = "\n" . $str if ($str !~ /^\n/); |
3436 |
$str =~ s/\n#[^\n]*/\n/g; |
3437 |
$str =~ s/\n\.[^\n]+/\n/g; |
3438 |
$str =~ s/\n\n+/\n/g; |
3439 |
$str =~ s/^\s+//; |
3440 |
$str =~ s/\s+$//; |
3441 |
return if ($str eq ''); |
3442 |
|
3443 |
if ($str =~ /^([\w\d]+)/) { |
3444 |
&perror("WARN", $file, -1, "extra item placed in the ". |
3445 |
"$section section, ". |
3446 |
"for example, \"$1\"."); |
3447 |
} else { |
3448 |
&perror("WARN", $file, -1, "extra item placed in the ". |
3449 |
"$section section."); |
3450 |
} |
3451 |
} |
3452 |
|
3453 |
sub checkorder { |
3454 |
my($section, $str, $file, @order) = @_; |
3455 |
my(@items, $i, $j, $k, $invalidorder); |
3456 |
|
3457 |
print "OK: checking the order of $section section.\n" if ($verbose); |
3458 |
$str //= ''; |
3459 |
|
3460 |
@items = (); |
3461 |
foreach my $i (split("\n", $str)) { |
3462 |
$i =~ s/[+?]?=.*$//; |
3463 |
push(@items, $i); |
3464 |
} |
3465 |
|
3466 |
@items = reverse(@items); |
3467 |
$j = -1; |
3468 |
$invalidorder = 0; |
3469 |
while (scalar(@items)) { |
3470 |
$i = pop(@items); |
3471 |
$k = 0; |
3472 |
while ($k < scalar(@order) && $order[$k] ne $i) { |
3473 |
if (defined $order[$k] && |
3474 |
$order[$k] =~ /[\.\*\+\?\{\}\[\]\^\$\|]/ && |
3475 |
$i =~ /$order[$k]/) { |
3476 |
last; |
3477 |
} |
3478 |
$k++; |
3479 |
} |
3480 |
if (defined $order[$k] && $order[$k] =~ /[\.\*\+\?\{\}\[\]\^\$\|]/ && |
3481 |
$i =~ /$order[$k]/) { |
3482 |
if ($k < $j) { |
3483 |
&perror("FATAL", $file, -1, "$i appears out-of-order."); |
3484 |
$invalidorder++; |
3485 |
} else { |
3486 |
print "OK: seen $i, in order.\n" if ($verbose); |
3487 |
} |
3488 |
$j = $k; |
3489 |
} elsif (defined $order[$k] && $order[$k] eq $i) { |
3490 |
if ($k < $j) { |
3491 |
&perror("FATAL", $file, -1, "$i appears out-of-order."); |
3492 |
$invalidorder++; |
3493 |
} else { |
3494 |
print "OK: seen $i, in order.\n" if ($verbose); |
3495 |
} |
3496 |
$j = $k; |
3497 |
# This if condition tests for .if, .else (in all forms), |
3498 |
# .for and .endfor and .include |
3499 |
} elsif ($i !~ m/^\.(if|el|endif|for|endfor|include)/) { |
3500 |
&perror("FATAL", $file, -1, "extra item \"$i\" placed in the ". |
3501 |
"$section section."); |
3502 |
} |
3503 |
} |
3504 |
if ($invalidorder) { |
3505 |
&perror("FATAL", $file, -1, "order must be " . join('/', @order) . '.'); |
3506 |
} else { |
3507 |
print "OK: $section section is ordered properly.\n" |
3508 |
if ($verbose); |
3509 |
} |
3510 |
} |
3511 |
|
3512 |
sub checkearlier { |
3513 |
my($file, $str, @varnames) = @_; |
3514 |
|
3515 |
$str //= ''; |
3516 |
|
3517 |
print "OK: checking items that have to appear earlier.\n" if ($verbose); |
3518 |
foreach my $i (@varnames) { |
3519 |
if ($str =~ /\n($i)\??=/) { |
3520 |
&perror("WARN", $file, -1, "\"$1\" has to appear earlier."); |
3521 |
} |
3522 |
} |
3523 |
} |
3524 |
|
3525 |
sub linenumber { |
3526 |
my $text = shift; |
3527 |
my @lines; |
3528 |
|
3529 |
@lines = split /\n/, $text; |
3530 |
|
3531 |
return scalar(@lines) - 1; |
3532 |
} |
3533 |
|
3534 |
sub abspathname { |
3535 |
my($str, $file) = @_; |
3536 |
my($s, $i, %cmdnames); |
3537 |
my($pre); |
3538 |
|
3539 |
# trim all trailing backslash and newline |
3540 |
$str =~ s/\\\n\s*/ /g; |
3541 |
|
3542 |
# ignore parameter string to reinplace command |
3543 |
$str =~ s/([ \t][\@-]?(?:sed|\$[\{\(]SED[\}\)]|\$[\{\(]REINPLACE_CMD[\}\)]))((?:\s+\-\w+)*\s+(?:"(?:\\"|[^"\n])*"|'(?:\\'|[^'\n])*'))+(.*)/$1$3/g; #' |
3544 |
|
3545 |
# ignore parameter string to echo command |
3546 |
# XXX: This next pattern crashes Perl 5.8.7. |
3547 |
#$str =~ s/[ \t][\@-]?(echo|\$[\{\(]ECHO[\}\)]|\$[\{\(]ECHO_MSG[\}\)])[ \t]+("(\\'|\\"|[^"])*"|'(\\'|\\"|[^"])*')[ \t]*[;\n]//; #' |
3548 |
$str =~ s/[ \t][\@-]?(echo|\$[\{\(]ECHO[\}\)]|\$[\{\(]ECHO_MSG[\}\)])[ \t]+.*(;|$)//m; #' |
3549 |
|
3550 |
print "OK: checking direct use of full pathnames in $file.\n" |
3551 |
if ($verbose); |
3552 |
foreach my $s (split(/\n+/, $str)) { |
3553 |
$i = ''; |
3554 |
$s =~ s/#.*$//; |
3555 |
if ($s =~ /(^|[ \t\@'"-])(\/[\w\d])/) { #' |
3556 |
# suspected pathnames are recorded. |
3557 |
$i = $2 . $'; |
3558 |
$pre = $` . $1; |
3559 |
|
3560 |
if ($pre =~ /MASTER_SITE_SUBDIR/) { |
3561 |
# MASTER_SITE_SUBDIR lines are ok. |
3562 |
$i = ''; |
3563 |
} |
3564 |
if ($s =~ /\$\{[^}]*?\Q$i\E/) { |
3565 |
# If we're inside a make variable, we probably do not have |
3566 |
# an absolute path. |
3567 |
$i = ''; |
3568 |
} |
3569 |
} |
3570 |
if ($i ne '' && ! grep {$i =~ m|^$_|} @ALLOWED_FULL_PATHS) { |
3571 |
$i =~ s/\s.*$//; |
3572 |
$i =~ s/['"].*$//; #' |
3573 |
$i = substr($i, 0, 20) . '...' if (20 < length($i)); |
3574 |
&perror("WARN", $file, -1, "possible use of absolute pathname ". |
3575 |
"\"$i\"."); |
3576 |
} |
3577 |
} |
3578 |
|
3579 |
foreach my $s (split(/\n+/, $str)) { |
3580 |
print "OK: checking direct use of pathnames, phase 1.\n" if ($verbose); |
3581 |
%cmdnames = split(/\n|\t+/, <<EOF); |
3582 |
/usr/opt \${PORTSDIR} instead |
3583 |
$portsdir \${PORTSDIR} instead |
3584 |
$localbase \${PREFIX} or \${LOCALBASE}, as appropriate |
3585 |
EOF |
3586 |
foreach my $i (keys %cmdnames) { |
3587 |
if ($s =~ /^[^#]*$i/) { |
3588 |
&perror("WARN", $file, -1, "possible direct use of \"$&\" ". |
3589 |
"found. if so, use $cmdnames{$i}."); |
3590 |
} |
3591 |
} |
3592 |
|
3593 |
print "OK: checking direct use of pathnames, phase 2.\n" if ($verbose); |
3594 |
%cmdnames = split(/\n|\t+/, <<EOF); |
3595 |
distfiles \${DISTDIR} instead |
3596 |
pkg \${PKGDIR} instead |
3597 |
files \${FILESDIR} instead |
3598 |
scripts \${SCRIPTDIR} instead |
3599 |
patches \${PATCHDIR} instead |
3600 |
work \${WRKDIR} instead |
3601 |
EOF |
3602 |
foreach my $i (keys %cmdnames) { |
3603 |
# use (?![\w-]) instead of \b to exclude pkg-* |
3604 |
if ($file =~ /^[^#]*(\.\/|\$[\{\(]\.CURDIR[\}\)]\/|[ \t])(\b$i)(?![\w-])/ |
3605 |
&& $s !~ /^COMMENT(.)?=[^\n]+$i/m |
3606 |
&& $s !~ /^IGNORE(.)?=[^\n]+$i/m |
3607 |
&& $s !~ /^BROKEN(.)?=[^\n]+$i/m |
3608 |
&& $s !~ /^RESTRICTED(.)?=[^\n]+$i/m |
3609 |
&& $s !~ /^NO_PACKAGE(.)?=[^\n]+$i/m |
3610 |
&& $s !~ /^NO_CDROM(.)?=[^\n]+$i/m |
3611 |
&& $s !~ /^MAINTAINER(.)?=[^\n]+$i/m |
3612 |
&& $s !~ /^CATEGORIES(.)?=[^\n]+$i/m |
3613 |
&& $s !~ /^USES(.)?=[^\n]+$i/m |
3614 |
&& $s !~ /^WX_COMPS(.)?=[^\n]+$i/m |
3615 |
&& $s !~ /^SHEBANG_FILES(.)?=[^\n]+$i/m |
3616 |
&& $s !~ /^[A-Z0-9_]+_DESC=[^\n]+$i/m |
3617 |
&& $s !~ /^ONLY_FOR_ARCHS_REASON(.)?=[^\n]+$i/m |
3618 |
&& $s !~ /^NOT_FOR_ARCHS_REASON(.)?=[^\n]+$i/m) { |
3619 |
&perror("WARN", $file, -1, "possible direct use of \"$i\" \"$s\" ". |
3620 |
"found. if so, use $cmdnames{$i}."); |
3621 |
} |
3622 |
} |
3623 |
} |
3624 |
} |
3625 |
|
3626 |
sub get_makevar { |
3627 |
my($cmd, $result); |
3628 |
|
3629 |
$cmd = join(' -V ', "make $makeenv MASTER_SITE_BACKUP=''", map { "'$_'" } @_); |
3630 |
$result = `$cmd`; |
3631 |
chomp $result; |
3632 |
|
3633 |
$result =~ s/\n\n/\n\0\n/g; |
3634 |
if (${^CHILD_ERROR_NATIVE} != 0) { |
3635 |
die "\nFATAL ERROR: make(1) died with status ${^CHILD_ERROR_NATIVE} and returned '$result'"; |
3636 |
} |
3637 |
|
3638 |
return $result; |
3639 |
} |
3640 |
|
3641 |
sub get_makevar_raw { |
3642 |
my($cmd, $result); |
3643 |
|
3644 |
$cmd = join(' -XV ', "make $makeenv MASTER_SITE_BACKUP=''", map { "'$_'" } @_); |
3645 |
$result = `$cmd`; |
3646 |
chomp $result; |
3647 |
|
3648 |
$result =~ s/\n\n/\n\0\n/g; |
3649 |
if (${^CHILD_ERROR_NATIVE} != 0) { |
3650 |
die "\nFATAL ERROR: make(1) died with status ${^CHILD_ERROR_NATIVE} and returned '$result'"; |
3651 |
} |
3652 |
|
3653 |
return $result; |
3654 |
} |
3655 |
|
3656 |
sub is_predefined { |
3657 |
my($url, $file) = @_; |
3658 |
my($site, $site_re); |
3659 |
my $subdir_re = quotemeta quotemeta '/%SUBDIR%/'; |
3660 |
for my $site (keys %predefined) { |
3661 |
$site_re = quotemeta $site; |
3662 |
$site_re =~ s,$subdir_re,/(.*)/,; |
3663 |
|
3664 |
if ($url =~ /$site_re/ && $file) { |
3665 |
my $pe = "how about using \"\${MASTER_SITE_$predefined{$site}}\" "; |
3666 |
if ($1) { |
3667 |
$pe .= "with \"MASTER_SITE_SUBDIR=$1\", "; |
3668 |
} |
3669 |
$pe .= "instead of \"$url\"?"; |
3670 |
&perror("WARN", $file, -1, $pe); |
3671 |
return &TRUE; |
3672 |
} elsif ($url =~ /$site_re/ && !$file) { |
3673 |
return &TRUE; |
3674 |
} |
3675 |
} |
3676 |
undef; |
3677 |
} |
3678 |
|
3679 |
sub urlcheck { |
3680 |
my ($url, $file) = @_; |
3681 |
if ($url !~ m#^\w+://#) { |
3682 |
&perror("WARN", $file, -1, "\"$url\" doesn't appear to be a URL to me."); |
3683 |
} |
3684 |
if ($url !~ m#/(:[^/:]+)?$# && $url !~ m#:$#) { |
3685 |
&perror("FATAL", $file, -1, "URL \"$url\" should ". |
3686 |
"end with \"/\" or a group name (e.g. :something)."); |
3687 |
} |
3688 |
if ($url =~ m#://[^/]*:/#) { |
3689 |
&perror("FATAL", $file, -1, "URL \"$url\" contains ". |
3690 |
"extra \":\"."); |
3691 |
} |
3692 |
} |
3693 |
|
3694 |
# GNOME wants INSTALL_ICONS, but Qt-based applications, including KDE, don't. |
3695 |
# Be pessimistic: everything needs it unless we know it doesn't. |
3696 |
sub needs_installs_icons { |
3697 |
return $makevar{USE_QT5} eq '' |
3698 |
} |
3699 |
|
3700 |
sub TRUE {1;} |
3701 |
|
3702 |
# Local variables: |
3703 |
# tab-width: 4 |
3704 |
# End: |