__init__.py 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. """
  2. BitBake Parsers
  3. File parsers for the BitBake build tools.
  4. """
  5. # Copyright (C) 2003, 2004 Chris Larson
  6. # Copyright (C) 2003, 2004 Phil Blundell
  7. #
  8. # This program is free software; you can redistribute it and/or modify
  9. # it under the terms of the GNU General Public License version 2 as
  10. # published by the Free Software Foundation.
  11. #
  12. # This program is distributed in the hope that it will be useful,
  13. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. # GNU General Public License for more details.
  16. #
  17. # You should have received a copy of the GNU General Public License along
  18. # with this program; if not, write to the Free Software Foundation, Inc.,
  19. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  20. #
  21. # Based on functions from the base bb module, Copyright 2003 Holger Schurig
  22. handlers = []
  23. import errno
  24. import logging
  25. import os
  26. import stat
  27. import bb
  28. import bb.utils
  29. import bb.siggen
  30. logger = logging.getLogger("BitBake.Parsing")
  31. class ParseError(Exception):
  32. """Exception raised when parsing fails"""
  33. def __init__(self, msg, filename, lineno=0):
  34. self.msg = msg
  35. self.filename = filename
  36. self.lineno = lineno
  37. Exception.__init__(self, msg, filename, lineno)
  38. def __str__(self):
  39. if self.lineno:
  40. return "ParseError at %s:%d: %s" % (self.filename, self.lineno, self.msg)
  41. else:
  42. return "ParseError in %s: %s" % (self.filename, self.msg)
  43. class SkipRecipe(Exception):
  44. """Exception raised to skip this recipe"""
  45. class SkipPackage(SkipRecipe):
  46. """Exception raised to skip this recipe (use SkipRecipe in new code)"""
  47. __mtime_cache = {}
  48. def cached_mtime(f):
  49. if f not in __mtime_cache:
  50. __mtime_cache[f] = os.stat(f)[stat.ST_MTIME]
  51. return __mtime_cache[f]
  52. def cached_mtime_noerror(f):
  53. if f not in __mtime_cache:
  54. try:
  55. __mtime_cache[f] = os.stat(f)[stat.ST_MTIME]
  56. except OSError:
  57. return 0
  58. return __mtime_cache[f]
  59. def update_mtime(f):
  60. try:
  61. __mtime_cache[f] = os.stat(f)[stat.ST_MTIME]
  62. except OSError:
  63. if f in __mtime_cache:
  64. del __mtime_cache[f]
  65. return 0
  66. return __mtime_cache[f]
  67. def update_cache(f):
  68. if f in __mtime_cache:
  69. logger.debug(1, "Updating mtime cache for %s" % f)
  70. update_mtime(f)
  71. def mark_dependency(d, f):
  72. if f.startswith('./'):
  73. f = "%s/%s" % (os.getcwd(), f[2:])
  74. deps = (d.getVar('__depends', False) or [])
  75. s = (f, cached_mtime_noerror(f))
  76. if s not in deps:
  77. deps.append(s)
  78. d.setVar('__depends', deps)
  79. def check_dependency(d, f):
  80. s = (f, cached_mtime_noerror(f))
  81. deps = (d.getVar('__depends', False) or [])
  82. return s in deps
  83. def supports(fn, data):
  84. """Returns true if we have a handler for this file, false otherwise"""
  85. for h in handlers:
  86. if h['supports'](fn, data):
  87. return 1
  88. return 0
  89. def handle(fn, data, include = 0):
  90. """Call the handler that is appropriate for this file"""
  91. for h in handlers:
  92. if h['supports'](fn, data):
  93. with data.inchistory.include(fn):
  94. return h['handle'](fn, data, include)
  95. raise ParseError("not a BitBake file", fn)
  96. def init(fn, data):
  97. for h in handlers:
  98. if h['supports'](fn):
  99. return h['init'](data)
  100. def init_parser(d):
  101. bb.parse.siggen = bb.siggen.init(d)
  102. def resolve_file(fn, d):
  103. if not os.path.isabs(fn):
  104. bbpath = d.getVar("BBPATH")
  105. newfn, attempts = bb.utils.which(bbpath, fn, history=True)
  106. for af in attempts:
  107. mark_dependency(d, af)
  108. if not newfn:
  109. raise IOError(errno.ENOENT, "file %s not found in %s" % (fn, bbpath))
  110. fn = newfn
  111. mark_dependency(d, fn)
  112. if not os.path.isfile(fn):
  113. raise IOError(errno.ENOENT, "file %s not found" % fn)
  114. return fn
  115. # Used by OpenEmbedded metadata
  116. __pkgsplit_cache__={}
  117. def vars_from_file(mypkg, d):
  118. if not mypkg or not mypkg.endswith((".bb", ".bbappend")):
  119. return (None, None, None)
  120. if mypkg in __pkgsplit_cache__:
  121. return __pkgsplit_cache__[mypkg]
  122. myfile = os.path.splitext(os.path.basename(mypkg))
  123. parts = myfile[0].split('_')
  124. __pkgsplit_cache__[mypkg] = parts
  125. if len(parts) > 3:
  126. raise ParseError("Unable to generate default variables from filename (too many underscores)", mypkg)
  127. exp = 3 - len(parts)
  128. tmplist = []
  129. while exp != 0:
  130. exp -= 1
  131. tmplist.append(None)
  132. parts.extend(tmplist)
  133. return parts
  134. def get_file_depends(d):
  135. '''Return the dependent files'''
  136. dep_files = []
  137. depends = d.getVar('__base_depends', False) or []
  138. depends = depends + (d.getVar('__depends', False) or [])
  139. for (fn, _) in depends:
  140. dep_files.append(os.path.abspath(fn))
  141. return " ".join(dep_files)
  142. from bb.parse.parse_py import __version__, ConfHandler, BBHandler