__init__.py 5.0 KB

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