Don't use Build.VERSION_CODES as it's not in 1.5
[zxing.git] / cpp / scons / sconsign.py
1 #! /usr/bin/env python
2 #
3 # SCons - a Software Constructor
4 #
5 # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 The SCons Foundation
6 #
7 # Permission is hereby granted, free of charge, to any person obtaining
8 # a copy of this software and associated documentation files (the
9 # "Software"), to deal in the Software without restriction, including
10 # without limitation the rights to use, copy, modify, merge, publish,
11 # distribute, sublicense, and/or sell copies of the Software, and to
12 # permit persons to whom the Software is furnished to do so, subject to
13 # the following conditions:
14 #
15 # The above copyright notice and this permission notice shall be included
16 # in all copies or substantial portions of the Software.
17 #
18 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
19 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
20 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
26 __revision__ = "src/script/sconsign.py 5023 2010/06/14 22:05:46 scons"
27
28 __version__ = "2.0.0.final.0"
29
30 __build__ = "r5023"
31
32 __buildsys__ = "scons-dev"
33
34 __date__ = "2010/06/14 22:05:46"
35
36 __developer__ = "scons"
37
38 import os
39 import sys
40 import time
41
42 ##############################################################################
43 # BEGIN STANDARD SCons SCRIPT HEADER
44 #
45 # This is the cut-and-paste logic so that a self-contained script can
46 # interoperate correctly with different SCons versions and installation
47 # locations for the engine.  If you modify anything in this section, you
48 # should also change other scripts that use this same header.
49 ##############################################################################
50
51 # Strip the script directory from sys.path() so on case-insensitive
52 # (WIN32) systems Python doesn't think that the "scons" script is the
53 # "SCons" package.  Replace it with our own library directories
54 # (version-specific first, in case they installed by hand there,
55 # followed by generic) so we pick up the right version of the build
56 # engine modules if they're in either directory.
57
58 script_dir = sys.path[0]
59
60 if script_dir in sys.path:
61     sys.path.remove(script_dir)
62
63 libs = []
64
65 if "SCONS_LIB_DIR" in os.environ:
66     libs.append(os.environ["SCONS_LIB_DIR"])
67
68 local_version = 'scons-local-' + __version__
69 local = 'scons-local'
70 if script_dir:
71     local_version = os.path.join(script_dir, local_version)
72     local = os.path.join(script_dir, local)
73 libs.append(os.path.abspath(local_version))
74 libs.append(os.path.abspath(local))
75
76 scons_version = 'scons-%s' % __version__
77
78 prefs = []
79
80 if sys.platform == 'win32':
81     # sys.prefix is (likely) C:\Python*;
82     # check only C:\Python*.
83     prefs.append(sys.prefix)
84     prefs.append(os.path.join(sys.prefix, 'Lib', 'site-packages'))
85 else:
86     # On other (POSIX) platforms, things are more complicated due to
87     # the variety of path names and library locations.  Try to be smart
88     # about it.
89     if script_dir == 'bin':
90         # script_dir is `pwd`/bin;
91         # check `pwd`/lib/scons*.
92         prefs.append(os.getcwd())
93     else:
94         if script_dir == '.' or script_dir == '':
95             script_dir = os.getcwd()
96         head, tail = os.path.split(script_dir)
97         if tail == "bin":
98             # script_dir is /foo/bin;
99             # check /foo/lib/scons*.
100             prefs.append(head)
101
102     head, tail = os.path.split(sys.prefix)
103     if tail == "usr":
104         # sys.prefix is /foo/usr;
105         # check /foo/usr/lib/scons* first,
106         # then /foo/usr/local/lib/scons*.
107         prefs.append(sys.prefix)
108         prefs.append(os.path.join(sys.prefix, "local"))
109     elif tail == "local":
110         h, t = os.path.split(head)
111         if t == "usr":
112             # sys.prefix is /foo/usr/local;
113             # check /foo/usr/local/lib/scons* first,
114             # then /foo/usr/lib/scons*.
115             prefs.append(sys.prefix)
116             prefs.append(head)
117         else:
118             # sys.prefix is /foo/local;
119             # check only /foo/local/lib/scons*.
120             prefs.append(sys.prefix)
121     else:
122         # sys.prefix is /foo (ends in neither /usr or /local);
123         # check only /foo/lib/scons*.
124         prefs.append(sys.prefix)
125
126     temp = [os.path.join(x, 'lib') for x in prefs]
127     temp.extend([os.path.join(x,
128                                            'lib',
129                                            'python' + sys.version[:3],
130                                            'site-packages') for x in prefs])
131     prefs = temp
132
133     # Add the parent directory of the current python's library to the
134     # preferences.  On SuSE-91/AMD64, for example, this is /usr/lib64,
135     # not /usr/lib.
136     try:
137         libpath = os.__file__
138     except AttributeError:
139         pass
140     else:
141         # Split /usr/libfoo/python*/os.py to /usr/libfoo/python*.
142         libpath, tail = os.path.split(libpath)
143         # Split /usr/libfoo/python* to /usr/libfoo
144         libpath, tail = os.path.split(libpath)
145         # Check /usr/libfoo/scons*.
146         prefs.append(libpath)
147
148     try:
149         import pkg_resources
150     except ImportError:
151         pass
152     else:
153         # when running from an egg add the egg's directory 
154         try:
155             d = pkg_resources.get_distribution('scons')
156         except pkg_resources.DistributionNotFound:
157             pass
158         else:
159             prefs.append(d.location)
160
161 # Look first for 'scons-__version__' in all of our preference libs,
162 # then for 'scons'.
163 libs.extend([os.path.join(x, scons_version) for x in prefs])
164 libs.extend([os.path.join(x, 'scons') for x in prefs])
165
166 sys.path = libs + sys.path
167
168 ##############################################################################
169 # END STANDARD SCons SCRIPT HEADER
170 ##############################################################################
171
172 import SCons.compat   # so pickle will import cPickle instead
173
174 import whichdb
175 import pickle
176 import imp
177
178 import SCons.SConsign
179
180 def my_whichdb(filename):
181     if filename[-7:] == ".dblite":
182         return "SCons.dblite"
183     try:
184         f = open(filename + ".dblite", "rb")
185         f.close()
186         return "SCons.dblite"
187     except IOError:
188         pass
189     return _orig_whichdb(filename)
190
191 _orig_whichdb = whichdb.whichdb
192 whichdb.whichdb = my_whichdb
193
194 def my_import(mname):
195     if '.' in mname:
196         i = mname.rfind('.')
197         parent = my_import(mname[:i])
198         fp, pathname, description = imp.find_module(mname[i+1:],
199                                                     parent.__path__)
200     else:
201         fp, pathname, description = imp.find_module(mname)
202     return imp.load_module(mname, fp, pathname, description)
203
204 class Flagger(object):
205     default_value = 1
206     def __setitem__(self, item, value):
207         self.__dict__[item] = value
208         self.default_value = 0
209     def __getitem__(self, item):
210         return self.__dict__.get(item, self.default_value)
211
212 Do_Call = None
213 Print_Directories = []
214 Print_Entries = []
215 Print_Flags = Flagger()
216 Verbose = 0
217 Readable = 0
218
219 def default_mapper(entry, name):
220     try:
221         val = eval("entry."+name)
222     except:
223         val = None
224     return str(val)
225
226 def map_action(entry, name):
227     try:
228         bact = entry.bact
229         bactsig = entry.bactsig
230     except AttributeError:
231         return None
232     return '%s [%s]' % (bactsig, bact)
233
234 def map_timestamp(entry, name):
235     try:
236         timestamp = entry.timestamp
237     except AttributeError:
238         timestamp = None
239     if Readable and timestamp:
240         return "'" + time.ctime(timestamp) + "'"
241     else:
242         return str(timestamp)
243
244 def map_bkids(entry, name):
245     try:
246         bkids = entry.bsources + entry.bdepends + entry.bimplicit
247         bkidsigs = entry.bsourcesigs + entry.bdependsigs + entry.bimplicitsigs
248     except AttributeError:
249         return None
250     result = []
251     for i in range(len(bkids)):
252         result.append(nodeinfo_string(bkids[i], bkidsigs[i], "        "))
253     if result == []:
254         return None
255     return "\n        ".join(result)
256
257 map_field = {
258     'action'    : map_action,
259     'timestamp' : map_timestamp,
260     'bkids'     : map_bkids,
261 }
262
263 map_name = {
264     'implicit'  : 'bkids',
265 }
266
267 def field(name, entry, verbose=Verbose):
268     if not Print_Flags[name]:
269         return None
270     fieldname = map_name.get(name, name)
271     mapper = map_field.get(fieldname, default_mapper)
272     val = mapper(entry, name)
273     if verbose:
274         val = name + ": " + val
275     return val
276
277 def nodeinfo_raw(name, ninfo, prefix=""):
278     # This just formats the dictionary, which we would normally use str()
279     # to do, except that we want the keys sorted for deterministic output.
280     d = ninfo.__dict__
281     try:
282         keys = ninfo.field_list + ['_version_id']
283     except AttributeError:
284         keys = sorted(d.keys())
285     l = []
286     for k in keys:
287         l.append('%s: %s' % (repr(k), repr(d.get(k))))
288     if '\n' in name:
289         name = repr(name)
290     return name + ': {' + ', '.join(l) + '}'
291
292 def nodeinfo_cooked(name, ninfo, prefix=""):
293     try:
294         field_list = ninfo.field_list
295     except AttributeError:
296         field_list = []
297     if '\n' in name:
298         name = repr(name)
299     outlist = [name+':'] + [_f for _f in [field(x, ninfo, Verbose) for x in field_list] if _f]
300     if Verbose:
301         sep = '\n    ' + prefix
302     else:
303         sep = ' '
304     return sep.join(outlist)
305
306 nodeinfo_string = nodeinfo_cooked
307
308 def printfield(name, entry, prefix=""):
309     outlist = field("implicit", entry, 0)
310     if outlist:
311         if Verbose:
312             print "    implicit:"
313         print "        " + outlist
314     outact = field("action", entry, 0)
315     if outact:
316         if Verbose:
317             print "    action: " + outact
318         else:
319             print "        " + outact
320
321 def printentries(entries, location):
322     if Print_Entries:
323         for name in Print_Entries:
324             try:
325                 entry = entries[name]
326             except KeyError:
327                 sys.stderr.write("sconsign: no entry `%s' in `%s'\n" % (name, location))
328             else:
329                 try:
330                     ninfo = entry.ninfo
331                 except AttributeError:
332                     print name + ":"
333                 else:
334                     print nodeinfo_string(name, entry.ninfo)
335                 printfield(name, entry.binfo)
336     else:
337         for name in sorted(entries.keys()):
338             entry = entries[name]
339             try:
340                 ninfo = entry.ninfo
341             except AttributeError:
342                 print name + ":"
343             else:
344                 print nodeinfo_string(name, entry.ninfo)
345             printfield(name, entry.binfo)
346
347 class Do_SConsignDB(object):
348     def __init__(self, dbm_name, dbm):
349         self.dbm_name = dbm_name
350         self.dbm = dbm
351
352     def __call__(self, fname):
353         # The *dbm modules stick their own file suffixes on the names
354         # that are passed in.  This is causes us to jump through some
355         # hoops here to be able to allow the user
356         try:
357             # Try opening the specified file name.  Example:
358             #   SPECIFIED                  OPENED BY self.dbm.open()
359             #   ---------                  -------------------------
360             #   .sconsign               => .sconsign.dblite
361             #   .sconsign.dblite        => .sconsign.dblite.dblite
362             db = self.dbm.open(fname, "r")
363         except (IOError, OSError), e:
364             print_e = e
365             try:
366                 # That didn't work, so try opening the base name,
367                 # so that if the actually passed in 'sconsign.dblite'
368                 # (for example), the dbm module will put the suffix back
369                 # on for us and open it anyway.
370                 db = self.dbm.open(os.path.splitext(fname)[0], "r")
371             except (IOError, OSError):
372                 # That didn't work either.  See if the file name
373                 # they specified just exists (independent of the dbm
374                 # suffix-mangling).
375                 try:
376                     open(fname, "r")
377                 except (IOError, OSError), e:
378                     # Nope, that file doesn't even exist, so report that
379                     # fact back.
380                     print_e = e
381                 sys.stderr.write("sconsign: %s\n" % (print_e))
382                 return
383         except KeyboardInterrupt:
384             raise
385         except pickle.UnpicklingError:
386             sys.stderr.write("sconsign: ignoring invalid `%s' file `%s'\n" % (self.dbm_name, fname))
387             return
388         except Exception, e:
389             sys.stderr.write("sconsign: ignoring invalid `%s' file `%s': %s\n" % (self.dbm_name, fname, e))
390             return
391
392         if Print_Directories:
393             for dir in Print_Directories:
394                 try:
395                     val = db[dir]
396                 except KeyError:
397                     sys.stderr.write("sconsign: no dir `%s' in `%s'\n" % (dir, args[0]))
398                 else:
399                     self.printentries(dir, val)
400         else:
401             for dir in sorted(db.keys()):
402                 self.printentries(dir, db[dir])
403
404     def printentries(self, dir, val):
405         print '=== ' + dir + ':'
406         printentries(pickle.loads(val), dir)
407
408 def Do_SConsignDir(name):
409     try:
410         fp = open(name, 'rb')
411     except (IOError, OSError), e:
412         sys.stderr.write("sconsign: %s\n" % (e))
413         return
414     try:
415         sconsign = SCons.SConsign.Dir(fp)
416     except KeyboardInterrupt:
417         raise
418     except pickle.UnpicklingError:
419         sys.stderr.write("sconsign: ignoring invalid .sconsign file `%s'\n" % (name))
420         return
421     except Exception, e:
422         sys.stderr.write("sconsign: ignoring invalid .sconsign file `%s': %s\n" % (name, e))
423         return
424     printentries(sconsign.entries, args[0])
425
426 ##############################################################################
427
428 import getopt
429
430 helpstr = """\
431 Usage: sconsign [OPTIONS] FILE [...]
432 Options:
433   -a, --act, --action         Print build action information.
434   -c, --csig                  Print content signature information.
435   -d DIR, --dir=DIR           Print only info about DIR.
436   -e ENTRY, --entry=ENTRY     Print only info about ENTRY.
437   -f FORMAT, --format=FORMAT  FILE is in the specified FORMAT.
438   -h, --help                  Print this message and exit.
439   -i, --implicit              Print implicit dependency information.
440   -r, --readable              Print timestamps in human-readable form.
441   --raw                       Print raw Python object representations.
442   -s, --size                  Print file sizes.
443   -t, --timestamp             Print timestamp information.
444   -v, --verbose               Verbose, describe each field.
445 """
446
447 opts, args = getopt.getopt(sys.argv[1:], "acd:e:f:hirstv",
448                             ['act', 'action',
449                              'csig', 'dir=', 'entry=',
450                              'format=', 'help', 'implicit',
451                              'raw', 'readable',
452                              'size', 'timestamp', 'verbose'])
453
454
455 for o, a in opts:
456     if o in ('-a', '--act', '--action'):
457         Print_Flags['action'] = 1
458     elif o in ('-c', '--csig'):
459         Print_Flags['csig'] = 1
460     elif o in ('-d', '--dir'):
461         Print_Directories.append(a)
462     elif o in ('-e', '--entry'):
463         Print_Entries.append(a)
464     elif o in ('-f', '--format'):
465         Module_Map = {'dblite'   : 'SCons.dblite',
466                       'sconsign' : None}
467         dbm_name = Module_Map.get(a, a)
468         if dbm_name:
469             try:
470                 dbm = my_import(dbm_name)
471             except:
472                 sys.stderr.write("sconsign: illegal file format `%s'\n" % a)
473                 print helpstr
474                 sys.exit(2)
475             Do_Call = Do_SConsignDB(a, dbm)
476         else:
477             Do_Call = Do_SConsignDir
478     elif o in ('-h', '--help'):
479         print helpstr
480         sys.exit(0)
481     elif o in ('-i', '--implicit'):
482         Print_Flags['implicit'] = 1
483     elif o in ('--raw',):
484         nodeinfo_string = nodeinfo_raw
485     elif o in ('-r', '--readable'):
486         Readable = 1
487     elif o in ('-s', '--size'):
488         Print_Flags['size'] = 1
489     elif o in ('-t', '--timestamp'):
490         Print_Flags['timestamp'] = 1
491     elif o in ('-v', '--verbose'):
492         Verbose = 1
493
494 if Do_Call:
495     for a in args:
496         Do_Call(a)
497 else:
498     for a in args:
499         dbm_name = whichdb.whichdb(a)
500         if dbm_name:
501             Map_Module = {'SCons.dblite' : 'dblite'}
502             dbm = my_import(dbm_name)
503             Do_SConsignDB(Map_Module.get(dbm_name, dbm_name), dbm)(a)
504         else:
505             Do_SConsignDir(a)
506
507 sys.exit(0)
508
509 # Local Variables:
510 # tab-width:4
511 # indent-tabs-mode:nil
512 # End:
513 # vim: set expandtab tabstop=4 shiftwidth=4: