Added some code to peer into a data structure in Maemian/Schedule.pm. Also added the
[maemian] / nokia-lintian / checks / rules
1 # rules -- lintian check script -*- perl -*-
2
3 # Copyright (C) 2006 Russ Allbery <rra@debian.org>
4 # Copyright (C) 2005 RenĂ© van Bevern <rvb@pro-linux.de>
5 #
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15
16 package Lintian::rules;
17 use strict;
18 use Tags;
19 use Util;
20 use Dep;
21
22 # The following targets are required per Policy.
23 my %required = map { $_ => 1 }
24     qw(build binary binary-arch binary-indep clean);
25
26 # Rules about required debhelper command ordering.  Each command is put into a
27 # class and the tag is issued if they're called in the wrong order for the
28 # classes.  Unknown commands won't trigger this flag.
29 my %debhelper_order =
30     (dh_makeshlibs => 1,
31      dh_shlibdeps  => 2,
32      dh_installdeb => 2,
33      dh_gencontrol => 2,
34      dh_builddeb   => 3);
35
36 sub run {
37
38 my $pkg = shift;
39 my $type = shift;
40
41 # Policy could be read as allowing debian/rules to be a symlink to some other
42 # file, and in a native Debian package it could be a symlink to a file that we
43 # didn't unpack.  Warn if it's a symlink (dpkg-source does as well) and skip
44 # all the tests if we then can't read it.
45 if (-l "debfiles/rules") {
46     tag "debian-rules-is-symlink", "";
47     return 0 unless -f "debfiles/rules";
48 }
49
50 #get architecture field:
51 unless (-d "fields") {
52     fail("directory in lintian laboratory for $type package $pkg missing: fields");
53 }
54
55 my $architecture = "";
56 if(open (IN, '<', "fields/architecture")) {
57     chomp($architecture = <IN>)
58 }
59 close(IN);
60
61 #get build-depends:
62 my $build_deps = "";
63 if (open(IN, '<', "fields/build-depends")) {
64     local $/ = undef;
65     chomp($build_deps .= <IN>);
66     close(IN);
67 }
68 if (open(IN, '<', "fields/build-depends-indep")) {
69     local $/ = undef;
70     chomp($build_deps .= <IN>);
71     close(IN);
72 }
73 $build_deps = Dep::parse($build_deps);
74
75
76 open(RULES, '<', 'debfiles/rules') or fail("Failed opening rules: $!");
77
78 # Check for required #!/usr/bin/make -f opening line.  Allow -r or -e; a
79 # strict reading of Policy doesn't allow either, but they seem harmless.
80 my $start = <RULES>;
81 tag "debian-rules-not-a-makefile", ""
82     unless $start =~ m%^\#!\s*/usr/bin/make\s+-[re]?f[re]?\s*$%;
83
84 # Scan debian/rules.  We would really like to let make do this for us, but
85 # unfortunately there doesn't seem to be a way to get make to syntax-check and
86 # analyze a makefile without running at least $(shell) commands.
87 #
88 # We skip some of the rule analysis if debian/rules includes any other files,
89 # since to chase all includes we'd have to have all of its build dependencies
90 # installed.
91 my $includes = 0;
92 my %seen;
93 local $_;
94 my @current_targets;
95 my %rules_per_target;
96 my $debhelper_group;
97 while (<RULES>) {
98     next if /^\s*\#/;
99     $includes = 1 if /^ *[s-]?include\s+/;
100
101     # Check for DH_COMPAT settings outside of any rule, which are now
102     # deprecated.  It's a bit easier structurally to do this here than in
103     # debhelper.
104     if (/^\s*(export\s+)?DH_COMPAT\s*:?=/ && keys(%seen) == 0) {
105         tag "debian-rules-sets-DH_COMPAT", "line $.";
106     }
107
108     # Check for problems that can occur anywhere in debian/rules.
109     if (/\$[\(\{]PWD[\)\}]/) {
110         tag "debian-rules-uses-pwd", "line $.";
111     }
112     if (/^\t\s*-(?:\$[\(\{]MAKE[\}\)]|make)\s.*(?:dist)?clean/ ||
113         /^\t\s*(?:\$[\(\{]MAKE[\}\)]|make)\s(?:.*\s)?-\w*i.*(?:dist)?clean/) {
114         tag "debian-rules-ignores-make-clean-error", "line $.";
115     }
116     if (/$[\(\{]DEB_BUILD_OPTS[\)\}]/) {
117         tag "debian-rules-uses-DEB_BUILD_OPTS", "line $.";
118     }
119
120     # Listing a rule as a dependency of .PHONY is sufficient to make it
121     # present for the purposes of GNU make and therefore the Policy
122     # requirement.
123     if (/^(?:[^:]+\s)?\.PHONY(?:\s[^:]+)?:(.+)/) {
124         my @targets = split (' ', $1);
125         for (@targets) {
126             $seen{$_}++ if $required{$_};
127         }
128     }
129
130     if (/^([^\s:][^:]*):/) {
131         @current_targets = split (' ', $1);
132         for (@current_targets) {
133             if (m/%/) {
134                 my $pattern = quotemeta $_;
135                 $pattern =~ s/\\%/.*/g;
136                 for my $target (keys %required) {
137                     $seen{$target}++ if $target =~ m/$pattern/;
138                 }
139             } else {
140                 $seen{$_}++ if $required{$_};
141             }
142         }
143         $debhelper_group = 0;
144     } else {
145         # If we have non-empty, non-comment lines, store them for all current
146         # targets and check whether debhelper programs are called in a
147         # reasonable order.
148         if (m/^\s+[^\#]/) {
149             foreach my $target (@current_targets) {
150                 $rules_per_target{$target} ||= [];
151                 push @{$rules_per_target{$target}}, $_;
152             }
153             if (m/^\s+(dh_\S+)\b/ and $debhelper_order{$1}) {
154                 my $command = $1;
155                 my $group = $debhelper_order{$command};
156                 if ($group < $debhelper_group) {
157                     tag "debian-rules-calls-debhelper-in-odd-order",
158                         $command, "(line $.)";
159                 } else {
160                     $debhelper_group = $group;
161                 }
162             }
163         }
164     }
165 }
166 close RULES;
167
168 unless ($includes) {
169     # Make sure all the required rules were seen.
170     for my $target (sort keys %required) {
171         tag "debian-rules-missing-required-target", $target
172             unless $seen{$target};
173     }
174
175     #check if we should have seen some dh_ calls:
176     if (Dep::implies($build_deps, Dep::parse("debhelper"))) {
177         #.desktop files usually imply dh_desktop:
178         if (scalar @{[glob("debfiles/*.desktop")]} &&
179             ! grep { /^\s*dh_desktop/ } map { @$_ } values %rules_per_target) {
180             tag "desktop-file-but-no-dh_desktop-call";
181         }
182     }
183 }
184
185 # Make sure we have no content for binary-arch if we are arch-indep:
186 if ($architecture eq "all" && scalar @{$rules_per_target{'binary-arch'} || []}) {
187     tag "binary-arch-rules-but-pkg-is-arch-indep";
188 }
189 }
190 1;
191
192 # vim: syntax=perl ts=8 sw=4