@@ -1085,6 +1085,73 @@ class DevtoolModifyTests(DevtoolBase):
# Try building
bitbake(testrecipe)
+ def test_devtool_modify_kernel_cfg_subdirs(self):
+ """
+ Regression test for YOCTO #15169: devtool modify of a kernel-yocto
+ recipe must not fail when an .scc file and the .cfg fragments it
+ references (via "kconf"/"patch" lines) live in different
+ FILESEXTRAPATHS subdirectories. Pre-fix, devtool computed each .cfg
+ file's path as dirname(<.scc file>) + <cfg filename>, which broke
+ whenever the .cfg file was not in the same directory as the .scc
+ file that references it.
+ """
+ testrecipe = 'virtual/kernel'
+ bb_vars = get_bb_vars(['PN', 'FILE'], testrecipe)
+ realrecipe = bb_vars['PN']
+
+ self.track_for_cleanup(self.workspacedir)
+ self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
+ self.add_command_to_tearDown('bitbake -c clean %s' % realrecipe)
+
+ # The created layer must outlive the 'bitbake-layers remove-layer'
+ # teardown command below: tearDown() runs the queued commands first
+ # and only then deletes track_for_cleanup() paths, so mkdtemp() +
+ # track_for_cleanup() removes the directory after remove-layer has
+ # run. A 'with tempfile.TemporaryDirectory()' here would instead
+ # delete it when the test body returns, i.e. before tearDown, leaving
+ # bblayers.conf pointing at a missing layer.
+ tempparentdir = tempfile.mkdtemp(prefix='devtoolqa')
+ self.track_for_cleanup(tempparentdir)
+ # bitbake-layers create-layer refuses to run if the target directory
+ # already exists, so use a not-yet-created subdirectory of tempparentdir
+ layerdir = os.path.join(tempparentdir, 'meta-selftest-kernelcfgsubdirs')
+ runCmd('bitbake-layers create-layer %s' % layerdir)
+ runCmd('bitbake-layers add-layer %s' % layerdir)
+ self.add_command_to_tearDown('bitbake-layers remove-layer %s || true' % layerdir)
+
+ recipedir = os.path.join(layerdir, 'recipes-kernel', 'linux', realrecipe)
+ bspdir = os.path.join(recipedir, 'bsp')
+ cfgdir = os.path.join(recipedir, 'cfg')
+ os.makedirs(bspdir)
+ os.makedirs(cfgdir)
+
+ # .scc lives in bsp/, references .cfg files that live in cfg/ -
+ # this is the exact split reported in the bug
+ with open(os.path.join(bspdir, 'selftest-cfgsubdirs.scc'), 'w') as f:
+ f.write('kconf hardware selftest-spi.cfg\n')
+ f.write('kconf hardware selftest-clock.cfg\n')
+ with open(os.path.join(cfgdir, 'selftest-spi.cfg'), 'w') as f:
+ f.write('# CONFIG_SPI_SELFTEST is not set\n')
+ with open(os.path.join(cfgdir, 'selftest-clock.cfg'), 'w') as f:
+ f.write('# CONFIG_COMMON_CLK_SELFTEST is not set\n')
+
+ appendfile = os.path.join(layerdir, 'recipes-kernel', 'linux', realrecipe + '_%.bbappend')
+ with open(appendfile, 'w') as f:
+ f.write('FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:${THISDIR}/${PN}/cfg:${THISDIR}/${PN}/bsp:"\n')
+ f.write('SRC_URI:append = " file://selftest-cfgsubdirs.scc"\n')
+ f.write('SRC_URI:append = " file://selftest-spi.cfg"\n')
+ f.write('SRC_URI:append = " file://selftest-clock.cfg"\n')
+
+ with tempfile.TemporaryDirectory(prefix='devtoolqa') as tempdir:
+ # Pre-fix (kirkstone-era), this raised FileNotFoundError while
+ # trying to shutil.copy2() selftest-spi.cfg/selftest-clock.cfg
+ # from inside bsp/ (the .scc's directory) instead of cfg/ (where
+ # they actually live).
+ result = runCmd('devtool modify %s -x %s' % (testrecipe, tempdir))
+ self.assertNotIn('FileNotFoundError', result.output)
+ self.assertExists(os.path.join(self.workspacedir, 'conf', 'layer.conf'),
+ 'Workspace directory not created')
+
def test_devtool_modify_virtual(self):
# Try modifying a virtual recipe
virtrecipe = 'virtual/make'
Add test_devtool_modify_kernel_cfg_subdirs which exercises a kernel-yocto recipe whose .scc file and the .cfg fragments it references (via "kconf"/"patch" lines) live in separate FILESEXTRAPATHS subdirectories (bsp/ and cfg/). This reproduces the layout from [YOCTO #15169], where devtool modify previously failed with FileNotFoundError while trying to copy the .cfg files: the path was computed as dirname(<.scc file>) + <cfg filename>, which broke whenever the .cfg file was not in the same directory as the .scc file that references it. The offending copy logic was removed in ce8190c519 ("devtool: Drop oe-local-files and simplify"); this test guards against a regression. Verified the test fails on d9328e3b0b (pre-fix, FileNotFoundError) and passes on current master. Signed-off-by: Siva Balasubramanian <sivakumar.bs@gmail.com> --- v2: - Use 'with tempfile.TemporaryDirectory()' for the devtool extract dir (Ross Burton review). - Keep tempfile.mkdtemp() + track_for_cleanup() for the created layer's parent dir rather than a 'with' block: OESelftestTestCase.tearDown() runs the queued teardown commands (including 'bitbake-layers remove-layer') before deleting track_for_cleanup() paths, so a body-scoped 'with' would remove the layer directory before remove-layer runs and leave bblayers.conf pointing at a missing layer. Verified by an oe-selftest run: teardown failed with a 'with' block, clean with mkdtemp()+track_for_cleanup(). Added '|| true' to the layer's remove-layer teardown, matching existing devtool tests. - Drop the 'bitbake -c cleansstate' call (Ross Burton review); the test only does 'devtool modify' so it was unnecessary. --- meta/lib/oeqa/selftest/cases/devtool.py | 67 +++++++++++++++++++++++++ 1 file changed, 67 insertions(+)