1#!/usr/bin/env python2
2
3"""
4defcheck.py -- Consistency check for the .def files.
5Copyright (C) 2006  Simon Budig <simon@gimp.org>
6
7This program is free software: you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 3 of the License, or
10(at your option) any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program.  If not, see <https://www.gnu.org/licenses/>.
19
20
21This is a hack to check the consistency of the .def files compared to
22the respective libraries.
23
24Invoke in the top level of the gimp source tree after compiling GIMP.
25If srcdir != builddir, run it in the build directory and pass the name
26of the source directory on the command-line.
27
28Needs the tool "nm" to work
29
30"""
31
32import sys, commands
33
34from os import path
35
36def_files = (
37   "libgimpbase/gimpbase.def",
38   "libgimpcolor/gimpcolor.def",
39   "libgimpconfig/gimpconfig.def",
40   "libgimp/gimp.def",
41   "libgimp/gimpui.def",
42   "libgimpmath/gimpmath.def",
43   "libgimpmodule/gimpmodule.def",
44   "libgimpthumb/gimpthumb.def",
45   "libgimpwidgets/gimpwidgets.def"
46)
47
48have_errors = 0
49
50srcdir = None
51if len(sys.argv) > 1:
52   srcdir = sys.argv[1]
53   if not path.exists(srcdir):
54      print "Directory '%s' does not exist" % srcdir
55      sys.exit (-1)
56
57for df in def_files:
58   directory, name = path.split (df)
59   basename, extension = name.split (".")
60   libname = path.join(directory, ".libs", "lib" + basename + "-*.so")
61
62   filename = df
63   if srcdir:
64      filename = path.join(srcdir, df)
65   try:
66      defsymbols = file (filename).read ().split ()[1:]
67   except IOError, message:
68      print message
69      if not srcdir:
70         print "You should run this script from the toplevel source directory."
71      sys.exit (-1)
72
73   doublesymbols = []
74   for i in range (len (defsymbols)-1, 0, -1):
75      if defsymbols[i] in defsymbols[:i]:
76         doublesymbols.append ((defsymbols[i], i+2))
77
78   unsortindex = -1
79   for i in range (len (defsymbols)-1):
80      if defsymbols[i] > defsymbols[i+1]:
81         unsortindex = i+1
82         break;
83
84   status, nm = commands.getstatusoutput ("nm --defined-only --extern-only " +
85                                          libname)
86   if status != 0:
87      print "trouble reading %s - has it been compiled?" % libname
88      continue
89
90   nmsymbols = nm.split()[2::3]
91   nmsymbols = [s for s in nmsymbols if s[0] != '_']
92
93   missing_defs = [s for s in nmsymbols  if s not in defsymbols]
94   missing_nms  = [s for s in defsymbols if s not in nmsymbols]
95
96   if unsortindex >= 0 or missing_defs or missing_nms or doublesymbols:
97      print
98      print "Problem found in", filename
99
100      if missing_defs:
101         print "  the following symbols are in the library,"
102         print "  but are not listed in the .def-file:"
103         for s in missing_defs:
104            print "     +", s
105         print
106
107      if missing_nms:
108         print "  the following symbols are listed in the .def-file,"
109         print "  but are not exported by the library."
110         for s in missing_nms:
111            print "     -", s
112         print
113
114      if doublesymbols:
115         print "  the following symbols are listed multiple times in the .def-file,"
116         for s in doublesymbols:
117            print "     : %s (line %d)" % s
118         print
119
120      if unsortindex >= 0:
121         print "  the .def-file is not properly sorted (line %d)" % (unsortindex + 2)
122         print
123
124      have_errors = -1
125
126sys.exit (have_errors)
127