summaryrefslogtreecommitdiffstats
path: root/meta/lib
diff options
context:
space:
mode:
Diffstat (limited to 'meta/lib')
-rw-r--r--meta/lib/bbconfigbuild/configfragments.py22
-rw-r--r--meta/lib/oe/__init__.py2
-rw-r--r--meta/lib/oe/reproducible.py5
-rw-r--r--meta/lib/oe/rust.py2
-rw-r--r--meta/lib/oe/tune.py81
-rw-r--r--meta/lib/oeqa/selftest/cases/devtool.py24
-rw-r--r--meta/lib/oeqa/selftest/cases/recipetool.py14
-rw-r--r--meta/lib/oeqa/selftest/cases/recipeutils.py4
-rw-r--r--meta/lib/oeqa/utils/commands.py15
9 files changed, 141 insertions, 28 deletions
diff --git a/meta/lib/bbconfigbuild/configfragments.py b/meta/lib/bbconfigbuild/configfragments.py
index c1dddc3e4c..61c33ac316 100644
--- a/meta/lib/bbconfigbuild/configfragments.py
+++ b/meta/lib/bbconfigbuild/configfragments.py
@@ -62,7 +62,22 @@ class ConfigFragmentsPlugin(LayerPlugin):
62 else: 62 else:
63 print('Name: {}\nPath: {}\nEnabled: {}\nSummary: {}\nDescription:\n{}\n'.format(f['name'], f['path'], 'yes' if is_enabled else 'no', f['summary'],''.join(f['description']))) 63 print('Name: {}\nPath: {}\nEnabled: {}\nSummary: {}\nDescription:\n{}\n'.format(f['name'], f['path'], 'yes' if is_enabled else 'no', f['summary'],''.join(f['description'])))
64 64
65 def print_builtin_fragments(builtin, enabled):
66 print('Available built-in fragments:')
67 builtin_dict = {i[0]:i[1] for i in [f.split(':') for f in builtin]}
68 for prefix,var in builtin_dict.items():
69 print('{}/...\tSets {} = ...'.format(prefix, var))
70 print('')
71 enabled_builtin_fragments = [f for f in enabled if self.builtin_fragment_exists(f)]
72 print('Enabled built-in fragments:')
73 for f in enabled_builtin_fragments:
74 prefix, value = f.split('/', 1)
75 print('{}\tSets {} = "{}"'.format(f, builtin_dict[prefix], value))
76 print('')
77
65 all_enabled_fragments = (self.tinfoil.config_data.getVar('OE_FRAGMENTS') or "").split() 78 all_enabled_fragments = (self.tinfoil.config_data.getVar('OE_FRAGMENTS') or "").split()
79 all_builtin_fragments = (self.tinfoil.config_data.getVar('OE_FRAGMENTS_BUILTIN') or "").split()
80 print_builtin_fragments(all_builtin_fragments, all_enabled_fragments)
66 81
67 for layername, layerdata in self.discover_fragments().items(): 82 for layername, layerdata in self.discover_fragments().items():
68 layerdir = layerdata['layerdir'] 83 layerdir = layerdata['layerdir']
@@ -89,6 +104,11 @@ class ConfigFragmentsPlugin(LayerPlugin):
89 return True 104 return True
90 return False 105 return False
91 106
107 def builtin_fragment_exists(self, fragmentname):
108 fragment_prefix = fragmentname.split("/",1)[0]
109 fragment_prefix_defs = set([f.split(':')[0] for f in self.tinfoil.config_data.getVar('OE_FRAGMENTS_BUILTIN').split()])
110 return fragment_prefix in fragment_prefix_defs
111
92 def create_conf(self, confpath): 112 def create_conf(self, confpath):
93 if not os.path.exists(confpath): 113 if not os.path.exists(confpath):
94 with open(confpath, 'w') as f: 114 with open(confpath, 'w') as f:
@@ -112,7 +132,7 @@ class ConfigFragmentsPlugin(LayerPlugin):
112 return " ".join(enabled_fragments), None, 0, True 132 return " ".join(enabled_fragments), None, 0, True
113 133
114 for f in args.fragmentname: 134 for f in args.fragmentname:
115 if not self.fragment_exists(f): 135 if not self.fragment_exists(f) and not self.builtin_fragment_exists(f):
116 raise Exception("Fragment {} does not exist; use 'list-fragments' to see the full list.".format(f)) 136 raise Exception("Fragment {} does not exist; use 'list-fragments' to see the full list.".format(f))
117 137
118 self.create_conf(args.confpath) 138 self.create_conf(args.confpath)
diff --git a/meta/lib/oe/__init__.py b/meta/lib/oe/__init__.py
index dd094a874a..73de774266 100644
--- a/meta/lib/oe/__init__.py
+++ b/meta/lib/oe/__init__.py
@@ -12,4 +12,4 @@ __path__ = extend_path(__path__, __name__)
12BBIMPORTS = ["qa", "data", "path", "utils", "types", "package", "packagedata", \ 12BBIMPORTS = ["qa", "data", "path", "utils", "types", "package", "packagedata", \
13 "packagegroup", "sstatesig", "lsb", "cachedpath", "license", "qemu", \ 13 "packagegroup", "sstatesig", "lsb", "cachedpath", "license", "qemu", \
14 "reproducible", "rust", "buildcfg", "go", "spdx30_tasks", "spdx_common", \ 14 "reproducible", "rust", "buildcfg", "go", "spdx30_tasks", "spdx_common", \
15 "cve_check"] 15 "cve_check", "tune"]
diff --git a/meta/lib/oe/reproducible.py b/meta/lib/oe/reproducible.py
index cdb38d5aa4..0270024a83 100644
--- a/meta/lib/oe/reproducible.py
+++ b/meta/lib/oe/reproducible.py
@@ -75,10 +75,11 @@ def get_source_date_epoch_from_known_files(d, sourcedir):
75 return source_date_epoch 75 return source_date_epoch
76 76
77def find_git_folder(d, sourcedir): 77def find_git_folder(d, sourcedir):
78 # First guess: UNPACKDIR/git 78 # First guess: UNPACKDIR/BB_GIT_DEFAULT_DESTSUFFIX
79 # This is the default git fetcher unpack path 79 # This is the default git fetcher unpack path
80 unpackdir = d.getVar('UNPACKDIR') 80 unpackdir = d.getVar('UNPACKDIR')
81 gitpath = os.path.join(unpackdir, "git/.git") 81 default_destsuffix = d.getVar('BB_GIT_DEFAULT_DESTSUFFIX')
82 gitpath = os.path.join(unpackdir, default_destsuffix, ".git")
82 if os.path.isdir(gitpath): 83 if os.path.isdir(gitpath):
83 return gitpath 84 return gitpath
84 85
diff --git a/meta/lib/oe/rust.py b/meta/lib/oe/rust.py
index 185553eeeb..1dc9cf150d 100644
--- a/meta/lib/oe/rust.py
+++ b/meta/lib/oe/rust.py
@@ -8,6 +8,4 @@
8def arch_to_rust_arch(arch): 8def arch_to_rust_arch(arch):
9 if arch == "ppc64le": 9 if arch == "ppc64le":
10 return "powerpc64le" 10 return "powerpc64le"
11 if arch in ('riscv32', 'riscv64'):
12 return arch + 'gc'
13 return arch 11 return arch
diff --git a/meta/lib/oe/tune.py b/meta/lib/oe/tune.py
new file mode 100644
index 0000000000..7fda19430d
--- /dev/null
+++ b/meta/lib/oe/tune.py
@@ -0,0 +1,81 @@
1#
2# Copyright OpenEmbedded Contributors
3#
4# SPDX-License-Identifier: GPL-2.0-only
5#
6
7# riscv_isa_to_tune(isa)
8#
9# Automatically translate a RISC-V ISA string to TUNE_FEATURES
10#
11# Abbreviations, such as rv32g -> rv32imaffd_zicsr_zifencei are supported.
12#
13# Profiles, such as rva22u64, are NOT supported, you must use ISA strings.
14#
15def riscv_isa_to_tune(isa):
16 _isa = isa.lower()
17
18 feature = []
19 iter = 0
20
21 # rv or riscv
22 if _isa[iter:].startswith('rv'):
23 feature.append('rv')
24 iter = iter + 2
25 elif _isa[iter:].startswith('riscv'):
26 feature.append('rv')
27 iter = iter + 5
28 else:
29 # Not a risc-v ISA!
30 return _isa
31
32 while (_isa[iter:]):
33 # Skip _ and whitespace
34 if _isa[iter] == '_' or _isa[iter].isspace():
35 iter = iter + 1
36 continue
37
38 # Length, just capture numbers here
39 if _isa[iter].isdigit():
40 iter_end = iter
41 while iter_end < len(_isa) and _isa[iter_end].isdigit():
42 iter_end = iter_end + 1
43
44 feature.append(_isa[iter:iter_end])
45 iter = iter_end
46 continue
47
48 # Typically i, e or g is next, followed by extensions.
49 # Extensions are single character, except for Z, Ss, Sh, Sm, Sv, and X
50
51 # If the extension starts with 'Z', 'S' or 'X' use the name until the next _, whitespace or end
52 if _isa[iter] in ['z', 's', 'x']:
53 ext_type = _isa[iter]
54 iter_end = iter + 1
55
56 # Multicharacter extension, these are supposed to have a _ before the next multicharacter extension
57 # See 37.4 and 37.5:
58 # 37.4: Underscores "_" may be used to separate ISA extensions...
59 # 37.5: All multi-letter extensions ... must be separated from other multi-letter extensions by an underscore...
60 # Some extensions permit only alphabetic characters, while others allow alphanumeric chartacters
61 while iter_end < len(_isa) and _isa[iter_end] != "_" and not _isa[iter_end].isspace():
62 iter_end = iter_end + 1
63
64 feature.append(_isa[iter:iter_end])
65 iter = iter_end
66 continue
67
68 # 'g' is special, it's an abbreviation for imafd_zicsr_zifencei
69 # When expanding the abbreviation, any additional letters must appear before the _z* extensions
70 if _isa[iter] == 'g':
71 _isa = 'imafd' + _isa[iter+1:] + '_zicsr_zifencei'
72 iter = 0
73 continue
74
75 feature.append(_isa[iter])
76 iter = iter + 1
77 continue
78
79 # Eliminate duplicates, but preserve the order
80 feature = list(dict.fromkeys(feature))
81 return ' '.join(feature)
diff --git a/meta/lib/oeqa/selftest/cases/devtool.py b/meta/lib/oeqa/selftest/cases/devtool.py
index 0155ee62ee..74a7727cc0 100644
--- a/meta/lib/oeqa/selftest/cases/devtool.py
+++ b/meta/lib/oeqa/selftest/cases/devtool.py
@@ -469,7 +469,7 @@ class DevtoolAddTests(DevtoolBase):
469 checkvars = {} 469 checkvars = {}
470 checkvars['LICENSE'] = 'GPL-2.0-only' 470 checkvars['LICENSE'] = 'GPL-2.0-only'
471 checkvars['LIC_FILES_CHKSUM'] = 'file://COPYING;md5=b234ee4d69f5fce4486a80fdaf4a4263' 471 checkvars['LIC_FILES_CHKSUM'] = 'file://COPYING;md5=b234ee4d69f5fce4486a80fdaf4a4263'
472 checkvars['S'] = '${WORKDIR}/git' 472 checkvars['S'] = None
473 checkvars['PV'] = '0.1+git' 473 checkvars['PV'] = '0.1+git'
474 checkvars['SRC_URI'] = 'git://git.yoctoproject.org/git/dbus-wait;protocol=https;branch=master' 474 checkvars['SRC_URI'] = 'git://git.yoctoproject.org/git/dbus-wait;protocol=https;branch=master'
475 checkvars['SRCREV'] = srcrev 475 checkvars['SRCREV'] = srcrev
@@ -565,7 +565,7 @@ class DevtoolAddTests(DevtoolBase):
565 recipefile = get_bb_var('FILE', testrecipe) 565 recipefile = get_bb_var('FILE', testrecipe)
566 self.assertIn('%s_%s.bb' % (testrecipe, testver), recipefile, 'Recipe file incorrectly named') 566 self.assertIn('%s_%s.bb' % (testrecipe, testver), recipefile, 'Recipe file incorrectly named')
567 checkvars = {} 567 checkvars = {}
568 checkvars['S'] = '${WORKDIR}/MarkupSafe-${PV}' 568 checkvars['S'] = '${UNPACKDIR}/MarkupSafe-${PV}'
569 checkvars['SRC_URI'] = url.replace(testver, '${PV}') 569 checkvars['SRC_URI'] = url.replace(testver, '${PV}')
570 self._test_recipe_contents(recipefile, checkvars, []) 570 self._test_recipe_contents(recipefile, checkvars, [])
571 # Try with version specified 571 # Try with version specified
@@ -582,7 +582,7 @@ class DevtoolAddTests(DevtoolBase):
582 recipefile = get_bb_var('FILE', testrecipe) 582 recipefile = get_bb_var('FILE', testrecipe)
583 self.assertIn('%s_%s.bb' % (testrecipe, fakever), recipefile, 'Recipe file incorrectly named') 583 self.assertIn('%s_%s.bb' % (testrecipe, fakever), recipefile, 'Recipe file incorrectly named')
584 checkvars = {} 584 checkvars = {}
585 checkvars['S'] = '${WORKDIR}/MarkupSafe-%s' % testver 585 checkvars['S'] = '${UNPACKDIR}/MarkupSafe-%s' % testver
586 checkvars['SRC_URI'] = url 586 checkvars['SRC_URI'] = url
587 self._test_recipe_contents(recipefile, checkvars, []) 587 self._test_recipe_contents(recipefile, checkvars, [])
588 588
@@ -609,7 +609,7 @@ class DevtoolAddTests(DevtoolBase):
609 recipefile = get_bb_var('FILE', testrecipe) 609 recipefile = get_bb_var('FILE', testrecipe)
610 self.assertIn('_git.bb', recipefile, 'Recipe file incorrectly named') 610 self.assertIn('_git.bb', recipefile, 'Recipe file incorrectly named')
611 checkvars = {} 611 checkvars = {}
612 checkvars['S'] = '${WORKDIR}/git' 612 checkvars['S'] = None
613 checkvars['PV'] = '1.0+git' 613 checkvars['PV'] = '1.0+git'
614 checkvars['SRC_URI'] = url_branch 614 checkvars['SRC_URI'] = url_branch
615 checkvars['SRCREV'] = '${AUTOREV}' 615 checkvars['SRCREV'] = '${AUTOREV}'
@@ -628,7 +628,7 @@ class DevtoolAddTests(DevtoolBase):
628 recipefile = get_bb_var('FILE', testrecipe) 628 recipefile = get_bb_var('FILE', testrecipe)
629 self.assertIn('_git.bb', recipefile, 'Recipe file incorrectly named') 629 self.assertIn('_git.bb', recipefile, 'Recipe file incorrectly named')
630 checkvars = {} 630 checkvars = {}
631 checkvars['S'] = '${WORKDIR}/git' 631 checkvars['S'] = None
632 checkvars['PV'] = '1.5+git' 632 checkvars['PV'] = '1.5+git'
633 checkvars['SRC_URI'] = url_branch 633 checkvars['SRC_URI'] = url_branch
634 checkvars['SRCREV'] = checkrev 634 checkvars['SRCREV'] = checkrev
@@ -1627,12 +1627,12 @@ class DevtoolUpdateTests(DevtoolBase):
1627 # Check preconditions 1627 # Check preconditions
1628 testrecipe = 'dos2unix' 1628 testrecipe = 'dos2unix'
1629 self.append_config('ERROR_QA:remove:pn-dos2unix = "patch-status"\n') 1629 self.append_config('ERROR_QA:remove:pn-dos2unix = "patch-status"\n')
1630 bb_vars = get_bb_vars(['SRC_URI', 'S', 'WORKDIR', 'FILE'], testrecipe) 1630 bb_vars = get_bb_vars(['SRC_URI', 'S', 'UNPACKDIR', 'FILE', 'BB_GIT_DEFAULT_DESTSUFFIX'], testrecipe)
1631 self.assertIn('git://', bb_vars['SRC_URI'], 'This test expects the %s recipe to be a git recipe' % testrecipe) 1631 self.assertIn('git://', bb_vars['SRC_URI'], 'This test expects the %s recipe to be a git recipe' % testrecipe)
1632 workdir_git = '%s/git/' % bb_vars['WORKDIR'] 1632 unpackdir_git = '%s/%s/' % (bb_vars['UNPACKDIR'], bb_vars['BB_GIT_DEFAULT_DESTSUFFIX'])
1633 if not bb_vars['S'].startswith(workdir_git): 1633 if not bb_vars['S'].startswith(unpackdir_git):
1634 self.fail('This test expects the %s recipe to be building from a subdirectory of the git repo' % testrecipe) 1634 self.fail('This test expects the %s recipe to be building from a subdirectory of the git repo' % testrecipe)
1635 subdir = bb_vars['S'].split(workdir_git, 1)[1] 1635 subdir = bb_vars['S'].split(unpackdir_git, 1)[1]
1636 # Clean up anything in the workdir/sysroot/sstate cache 1636 # Clean up anything in the workdir/sysroot/sstate cache
1637 bitbake('%s -c cleansstate' % testrecipe) 1637 bitbake('%s -c cleansstate' % testrecipe)
1638 # Try modifying a recipe 1638 # Try modifying a recipe
@@ -2414,7 +2414,7 @@ class DevtoolUpgradeTests(DevtoolBase):
2414 newsrctree = os.path.join(self.workspacedir, 'sources', newrecipename) 2414 newsrctree = os.path.join(self.workspacedir, 'sources', newrecipename)
2415 self.assertExists(newsrctree, 'Source directory not renamed') 2415 self.assertExists(newsrctree, 'Source directory not renamed')
2416 checkvars = {} 2416 checkvars = {}
2417 checkvars['S'] = '${WORKDIR}/%s-%s' % (recipename, recipever) 2417 checkvars['S'] = '${UNPACKDIR}/%s-%s' % (recipename, recipever)
2418 checkvars['SRC_URI'] = url 2418 checkvars['SRC_URI'] = url
2419 self._test_recipe_contents(newrecipefile, checkvars, []) 2419 self._test_recipe_contents(newrecipefile, checkvars, [])
2420 # Try again - change just name this time 2420 # Try again - change just name this time
@@ -2426,7 +2426,7 @@ class DevtoolUpgradeTests(DevtoolBase):
2426 self.assertNotExists(os.path.join(self.workspacedir, 'recipes', recipename), 'Old recipe directory still exists') 2426 self.assertNotExists(os.path.join(self.workspacedir, 'recipes', recipename), 'Old recipe directory still exists')
2427 self.assertExists(os.path.join(self.workspacedir, 'sources', newrecipename), 'Source directory not renamed') 2427 self.assertExists(os.path.join(self.workspacedir, 'sources', newrecipename), 'Source directory not renamed')
2428 checkvars = {} 2428 checkvars = {}
2429 checkvars['S'] = '${WORKDIR}/%s-${PV}' % recipename 2429 checkvars['S'] = '${UNPACKDIR}/%s-${PV}' % recipename
2430 checkvars['SRC_URI'] = url.replace(recipever, '${PV}') 2430 checkvars['SRC_URI'] = url.replace(recipever, '${PV}')
2431 self._test_recipe_contents(newrecipefile, checkvars, []) 2431 self._test_recipe_contents(newrecipefile, checkvars, [])
2432 # Try again - change just version this time 2432 # Try again - change just version this time
@@ -2437,7 +2437,7 @@ class DevtoolUpgradeTests(DevtoolBase):
2437 self.assertExists(newrecipefile, 'Recipe file not renamed') 2437 self.assertExists(newrecipefile, 'Recipe file not renamed')
2438 self.assertExists(os.path.join(self.workspacedir, 'sources', recipename), 'Source directory no longer exists') 2438 self.assertExists(os.path.join(self.workspacedir, 'sources', recipename), 'Source directory no longer exists')
2439 checkvars = {} 2439 checkvars = {}
2440 checkvars['S'] = '${WORKDIR}/${BPN}-%s' % recipever 2440 checkvars['S'] = '${UNPACKDIR}/${BPN}-%s' % recipever
2441 checkvars['SRC_URI'] = url 2441 checkvars['SRC_URI'] = url
2442 self._test_recipe_contents(newrecipefile, checkvars, []) 2442 self._test_recipe_contents(newrecipefile, checkvars, [])
2443 2443
diff --git a/meta/lib/oeqa/selftest/cases/recipetool.py b/meta/lib/oeqa/selftest/cases/recipetool.py
index 36557f270f..2a91f6c7ae 100644
--- a/meta/lib/oeqa/selftest/cases/recipetool.py
+++ b/meta/lib/oeqa/selftest/cases/recipetool.py
@@ -385,7 +385,7 @@ class RecipetoolCreateTests(RecipetoolBase):
385 checkvars = {} 385 checkvars = {}
386 checkvars['LICENSE'] = 'LGPL-2.1-only' 386 checkvars['LICENSE'] = 'LGPL-2.1-only'
387 checkvars['LIC_FILES_CHKSUM'] = 'file://COPYING;md5=7fbc338309ac38fefcd64b04bb903e34' 387 checkvars['LIC_FILES_CHKSUM'] = 'file://COPYING;md5=7fbc338309ac38fefcd64b04bb903e34'
388 checkvars['S'] = '${WORKDIR}/git' 388 checkvars['S'] = None
389 checkvars['PV'] = '1.11+git' 389 checkvars['PV'] = '1.11+git'
390 checkvars['SRC_URI'] = srcuri + ';branch=master' 390 checkvars['SRC_URI'] = srcuri + ';branch=master'
391 checkvars['DEPENDS'] = set(['libcheck', 'libjpeg-turbo', 'libpng', 'libx11', 'libxext', 'pango']) 391 checkvars['DEPENDS'] = set(['libcheck', 'libjpeg-turbo', 'libpng', 'libx11', 'libxext', 'pango'])
@@ -1144,10 +1144,10 @@ class RecipetoolAppendsrcTests(RecipetoolAppendsrcBase):
1144 1144
1145 def test_recipetool_appendsrcfile_srcdir_basic(self): 1145 def test_recipetool_appendsrcfile_srcdir_basic(self):
1146 testrecipe = 'bash' 1146 testrecipe = 'bash'
1147 bb_vars = get_bb_vars(['S', 'WORKDIR'], testrecipe) 1147 bb_vars = get_bb_vars(['S', 'UNPACKDIR'], testrecipe)
1148 srcdir = bb_vars['S'] 1148 srcdir = bb_vars['S']
1149 workdir = bb_vars['WORKDIR'] 1149 unpackdir = bb_vars['UNPACKDIR']
1150 subdir = os.path.relpath(srcdir, workdir) 1150 subdir = os.path.relpath(srcdir, unpackdir)
1151 self._test_appendsrcfile(testrecipe, 'a-file', srcdir=subdir) 1151 self._test_appendsrcfile(testrecipe, 'a-file', srcdir=subdir)
1152 1152
1153 def test_recipetool_appendsrcfile_existing_in_src_uri(self): 1153 def test_recipetool_appendsrcfile_existing_in_src_uri(self):
@@ -1196,10 +1196,10 @@ class RecipetoolAppendsrcTests(RecipetoolAppendsrcBase):
1196 def test_recipetool_appendsrcfile_replace_file_srcdir(self): 1196 def test_recipetool_appendsrcfile_replace_file_srcdir(self):
1197 testrecipe = 'bash' 1197 testrecipe = 'bash'
1198 filepath = 'Makefile.in' 1198 filepath = 'Makefile.in'
1199 bb_vars = get_bb_vars(['S', 'WORKDIR'], testrecipe) 1199 bb_vars = get_bb_vars(['S', 'UNPACKDIR'], testrecipe)
1200 srcdir = bb_vars['S'] 1200 srcdir = bb_vars['S']
1201 workdir = bb_vars['WORKDIR'] 1201 unpackdir = bb_vars['UNPACKDIR']
1202 subdir = os.path.relpath(srcdir, workdir) 1202 subdir = os.path.relpath(srcdir, unpackdir)
1203 1203
1204 self._test_appendsrcfile(testrecipe, filepath, srcdir=subdir) 1204 self._test_appendsrcfile(testrecipe, filepath, srcdir=subdir)
1205 bitbake('%s:do_unpack' % testrecipe) 1205 bitbake('%s:do_unpack' % testrecipe)
diff --git a/meta/lib/oeqa/selftest/cases/recipeutils.py b/meta/lib/oeqa/selftest/cases/recipeutils.py
index 9949737172..e697fd2920 100644
--- a/meta/lib/oeqa/selftest/cases/recipeutils.py
+++ b/meta/lib/oeqa/selftest/cases/recipeutils.py
@@ -72,7 +72,7 @@ class RecipeUtilsTests(OESelftestTestCase):
72 expected_patch = """ 72 expected_patch = """
73--- a/recipes-test/recipeutils/recipeutils-test_1.2.bb 73--- a/recipes-test/recipeutils/recipeutils-test_1.2.bb
74+++ b/recipes-test/recipeutils/recipeutils-test_1.2.bb 74+++ b/recipes-test/recipeutils/recipeutils-test_1.2.bb
75@@ -11,6 +11,4 @@ 75@@ -10,6 +10,4 @@
76 76
77 BBCLASSEXTEND = "native nativesdk" 77 BBCLASSEXTEND = "native nativesdk"
78 78
@@ -97,7 +97,7 @@ class RecipeUtilsTests(OESelftestTestCase):
97 expected_patch = """ 97 expected_patch = """
98--- a/recipes-test/recipeutils/recipeutils-test_1.2.bb 98--- a/recipes-test/recipeutils/recipeutils-test_1.2.bb
99+++ b/recipes-test/recipeutils/recipeutils-test_1.2.bb 99+++ b/recipes-test/recipeutils/recipeutils-test_1.2.bb
100@@ -11,6 +11,3 @@ 100@@ -10,6 +10,3 @@
101 101
102 BBCLASSEXTEND = "native nativesdk" 102 BBCLASSEXTEND = "native nativesdk"
103 103
diff --git a/meta/lib/oeqa/utils/commands.py b/meta/lib/oeqa/utils/commands.py
index 2a47f90e32..b60a6e6c38 100644
--- a/meta/lib/oeqa/utils/commands.py
+++ b/meta/lib/oeqa/utils/commands.py
@@ -285,7 +285,20 @@ def get_bb_vars(variables=None, target=None, postconfig=None):
285 return values 285 return values
286 286
287def get_bb_var(var, target=None, postconfig=None): 287def get_bb_var(var, target=None, postconfig=None):
288 return get_bb_vars([var], target, postconfig)[var] 288 if postconfig:
289 return bitbake("-e %s" % target or "", postconfig=postconfig).output
290 else:
291 # Fast-path for the non-postconfig case
292 cmd = ["bitbake-getvar", "--quiet", "--value", var]
293 if target:
294 cmd.extend(["--recipe", target])
295 try:
296 return subprocess.run(cmd, check=True, text=True, stdout=subprocess.PIPE).stdout.strip()
297 except subprocess.CalledProcessError as e:
298 # We need to return None not the empty string if the variable hasn't been set.
299 if e.returncode == 1:
300 return None
301 raise
289 302
290def get_test_layer(bblayers=None): 303def get_test_layer(bblayers=None):
291 if bblayers is None: 304 if bblayers is None: