portlint.pl 117 KB

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