From patchwork Thu Jun 18 07:19:07 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anders Heimer X-Patchwork-Id: 90409 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id E4249CD98ED for ; Thu, 18 Jun 2026 07:19:22 +0000 (UTC) Received: from AM0PR83CU005.outbound.protection.outlook.com (AM0PR83CU005.outbound.protection.outlook.com [52.101.69.3]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.14115.1781767159320576491 for ; Thu, 18 Jun 2026 00:19:19 -0700 Authentication-Results: mx.groups.io; dkim=fail reason="dkim: body hash did not verify" header.i=@est.tech header.s=selector1 header.b=nxF0xDXw; spf=pass (domain: est.tech, ip: 52.101.69.3, mailfrom: anders.heimer@est.tech) ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=HQuxqFa/mTsPKNr/6VqNN+HxhF0nZJtEGWF+8ZI4TShrHNt8zQQjC+2hYOK2pDxxChvSdw1DaWAbr9cPF0colNtrh8TLEkRX135Fqaheo6AmEtRLg09U0jZNfKcz5r/SppNum/0AL38IVlBDY8ujNoEQQkCu0esOIsS2WYmA2rzhWPHGWc7Jr5lb6RtACs9m9uEsG7A+Rta6ULPeGe0wudcteAw/mL1qD3Jp0dSHMQHtGPCeia1IfF1C974JLD3J/g4cX+L0+RRxEQb+JOpoOIMU1/fG9DrSM6MnaJVNqo6yQL+NXNrwkZeO9/42zUj0P1Jw/GIGqnAudgCiMsymLA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=IXI3R9Itaw4Y6Fp4LbxisGFd1te3nTL+EJVYEu99Bp8=; b=Vhh+A8bkQb2Xh1S4/NY67x6zLieP3e5vsIhA/kJ2wkAjcImSG9CjszL/P5urSXP31E9qYnJr4Yjz0J+M7FrcrkJx2dYgOMHABUZRBv21vyWExoEBBCtqfKarMIIOjH7JtX4WtqTZUtyC6fHKFSNm6haGVzrXkm68Xb7ZPda8q5+5aXMHIc2QsfQLXy/4tILKi/3gV44eSvuOjistwh9epQ8ZP+I/JOfaesNTpxisqD9DWpTszW0tcK8lw8pLzKibvOYEG7jI4zVFtD18Xzno2Rqg5o1fSAZTmuty2zq747A2H/wUEYWbpIKPvf/zvSk45f5Iz1sgDq8cIMkOzNianA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=est.tech; dmarc=pass action=none header.from=est.tech; dkim=pass header.d=est.tech; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=est.tech; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=IXI3R9Itaw4Y6Fp4LbxisGFd1te3nTL+EJVYEu99Bp8=; b=nxF0xDXwWbkbihWO9Gm7JKiTSoPqC+7k4O6m802ASpnMfOncjB4r1Q7sawCjiWV13+oe3yNeqJuG+lyo6k5ooaorQpvmuR1YsPGATbtxNfoCLZWE/FiUoBiQ10mr5T1Y1eV38VNn+zyWBuDzZ3W4R2Rwq0ov2LI3czlbsiZTN52ohFae9vW24eGRjkFIvnwOZmmOJ8N4WgA7RNWU6JQox4dPEkmmvLx4Uu0RLj/sgWIuZoBuJI8Sd2zp0ujdritSdlt+gvKn3t82O948meRGFNqGCZT4YFdwaYJawyd64/DQFyTEZEpPmxdzgVNzc1kfb+zDzqMzc4eYYY1VOr3jwQ== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=est.tech; Received: from DB9P189MB1641.EURP189.PROD.OUTLOOK.COM (2603:10a6:10:2ac::9) by VI0P189MB2776.EURP189.PROD.OUTLOOK.COM (2603:10a6:800:254::15) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.139.11; Thu, 18 Jun 2026 07:19:13 +0000 Received: from DB9P189MB1641.EURP189.PROD.OUTLOOK.COM ([fe80::90da:b700:f102:5c82]) by DB9P189MB1641.EURP189.PROD.OUTLOOK.COM ([fe80::90da:b700:f102:5c82%6]) with mapi id 15.21.0139.011; Thu, 18 Jun 2026 07:19:13 +0000 From: Anders Heimer To: openembedded-core@lists.openembedded.org CC: Anders Heimer Subject: [PATCH v2 1/2] package: replace copydebugsources shell pipelines Date: Thu, 18 Jun 2026 09:19:07 +0200 Message-ID: X-Mailer: git-send-email 2.43.0 In-Reply-To: References: X-ClientProxiedBy: LO4P123CA0090.GBRP123.PROD.OUTLOOK.COM (2603:10a6:600:190::23) To DB9P189MB1641.EURP189.PROD.OUTLOOK.COM (2603:10a6:10:2ac::9) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: DB9P189MB1641:EE_|VI0P189MB2776:EE_ X-MS-Office365-Filtering-Correlation-Id: 8adca7c8-4013-4d1b-c856-08decd09e5ee X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|23010399003|1800799024|376014|366016|11063799006|3023799007|56012099006|22082099003|18002099003; X-Microsoft-Antispam-Message-Info: 56NvPpTY8jyHYHcXwravYzqQgNRMNKa5VEN/lGEVoIjL93A19TtELpJ+2dVV8mnlZCgpg20bXMgfiOFw6x+Fq+jy0kwpoKWX+Wb6LLNBxlgCVHDIYSPl5rWTEJoy7eU/d+Wk0o29pwXetAxlp7A8VKKFE0iXBxKPJQDKWme269Qs0vie1kqiIWPhvVv6Ip3FJEnGzXTKSBj13L6nkuZ81te91hTH3E29Q9f0J0Ro9Zl02zGWGxN01XfJbBgUEYjuvEbBG6hc/djvLcEHWoI0Kv9ha54BxJrFQe/6TcS1zf0o6TAkyNVv3fgBhG7xEKv6mgsMytgm0VpJUAX+5Ij5m1yaIF1xnm5pcVvXB/vdsa7eG9PqD0BGCvi/FLdWFz/hxhsH+ASIvonVTrj2bBI8EB0C4P6E7aoK6aY2QNxbWGjqt/Ll8SIaCmg1lWL7TI+1LVTad4cb0B7fTyg7Ohgp8aTzmBDztDGQi3ne5/qmEd5u1uEPxwdOPVvBVabXwKV9op1kNxmYvbi7P7UhKUaedmGaKk3gtUe2PmHUTU8zHmFV24MDaqwtFTAR3hR1Ub6Dbpmd8c3sbOuI7LRC9jTOZ/Txg28M17wXuK32fNNtVbDhcZ4enAkA0D5cQcQwFnHNkHGq3s0g0VZlT1BGGhv2lrdVd+Q0Wcgb1rK8uBVz0bohySZMWQzGXKDgPkJf/MLJ X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:DB9P189MB1641.EURP189.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFS:(13230040)(23010399003)(1800799024)(376014)(366016)(11063799006)(3023799007)(56012099006)(22082099003)(18002099003);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: qz/99HgMd5+f25fsWmguZuP+zmF5yP4qqJ2bnfH/T0V14ugKKCMfbbLjQlGqzDNH4bYTj1RixMZ93rXgWsdUGhVmIgmFqsswvTEd09QYSBle8zlXBGhuB6vimKaviJe/XfA8sDFkDUaZHkHPiVuUzT3mVgXOQ66haUSzVOG3SHc9lz3hqYLbfY/F406lqjmr7FlZ9bVKG4rWEfDwsKgC0C9QQl/O6EjV6gPyVZaMbBSQp67K8A7CzldloAp12rWMeEe7+j/kIdTpzUbLQ1119Bfzm8rj6wXOow1ayNHksYV+2igFGaZ0fHgiRrlI5XtS7P/6GQF8oQqrahFqTo+pO9Z1iN08VxIjg2lShO06NOcHy1GplJNeM47cYS/2EP6138oT3tDrPot1314QlUyihMT87+AR2IBRS6LDBbVqHxwp++JFozavOjPyJCs9v0BsmwE2SzhA5egz6LouudBOK5h9AQYm5APdXCEq1RDzC46iLCeUdoZqTedEb+Ubhc359gAiEPTzxRXEGqVIgiAmIeWIk24IbeR8QjNyOp8klrBcNDScnhL2I9/LSzCTojPlHGJ+zoe+7o1+CpAEaG3qHW6m09YWWndBMW2Qv9rwNzcyZ/KlC8a/0umbX1YtE44olreTiuNEb4anAWRLLd1bOq65L7CFeDke1P0KVKG101Rkh1wv5hL9vuaQVXOEuMYo/A92dzrB5f3WMq8oJ8tEQuREnbdDkWIOxEuizndB6hcHJNlR407QKA40k8HlGU/NZvOEF65dgKua32kCR3CwPwa+KNIE5K2BnjtRWSiNTDEeTC8zThS2nWKr7lZkowr75DKXLaBQjCCVna2qAw/bfPdsDTHr0aVOAZYNPuTjkbf986Mg5pgmUSMlMNSIGCfXFM+eXrm2GzEzF18DUpGFcbupAWzLovXgGWJ4aW4Ys5b4v5YIKfbGxwlagtAP2JnYw63mQDtCFcuV16mjxwq0a3VJYbJMkod9yAKXXRUVq5MlWKQljP5Q/OaaCX9CeX4JAsNc8SVPkPqgKjnYp4ESg8wWSpisG25mYHleN2y+1erbWdVHLlCnNF6QZiCEg65MTUNSnjzcn8DyhAxdZcfsx5bpdBGT6AxZIANOXdhPynhyUdJQVAJ/QUtpH7maXHg/Y5prxgXKYPUjVAHbUT47gUJ93CyTJpGwu10bBL6E+hG/NW5TA8Yi5etuwMtJulbnUCk6XexTwccQHqSbfZpCeanIb/4KL9De6lwnl+KKSONhq8mS4m8n8oPq5x/C29/27JX+zblreE3LJ/05Hp5zCUBa17abtxCLMb7dLPFh642HknI2YIOPLcxyCRev9SUemHXIxxqpR/hJQ/WOB/fwzMThzouT30ZmsYB+0xF8wzvKFPID6GQc2IW6lGwX+xEEgkT0IPDC/ZJRlg7nfOHbErhLwjg29NUI5DCwGTrJFd06oGIo0hLcwGaYtrS2ltQD+PH6A8ibOtAp7oJnG5BrUMjum5eBA8JcJ65j2zztRLhemugtObX3z5reBXJzAVsFflTFadnuAHA+H8+JVca2MLLhS9kAylkEzSfj3bk3kFEzAKF7HEHthS/nO++WSXDcLR856z4Ybzzjoqc6Wvnbh2f1XZ9UN5qoKpgUJd53o7ETZB6UmgOQ5C6xsZHuwOYBj5G1baZqR+lrB7I7t66/vgFpGP0a16vaM/mD9x8haJ/hIeBjKJgkPLsqown/Z7d7UWCBtR+AwZ+p4gGr+l2w/g== X-OriginatorOrg: est.tech X-MS-Exchange-CrossTenant-Network-Message-Id: 8adca7c8-4013-4d1b-c856-08decd09e5ee X-MS-Exchange-CrossTenant-AuthSource: DB9P189MB1641.EURP189.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 18 Jun 2026 07:19:13.0027 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: d2585e63-66b9-44b6-a76e-4f4b217d97fd X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: +mIeNYBahIPK2oN5Uc+LvUyMhpOsq73s3L8nyRAftVwZsIyZLzcX5hX93AK3XWAU4ybljRhmzqbeHd07rE9e7Q== X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI0P189MB2776 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Thu, 18 Jun 2026 07:19:22 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/239063 Replace the sort/grep/sed parts of copydebugsources with Python filtering on the NUL-separated source list. Keep cpio since it is faster than doing it in python. Use an explicit prefix + "/" match before stripping the prefix so source selection is limited to files in the mapped debug source directory. Replace the find/sed symlink fixup pipeline with os.walk() plus cpio, use an argv-list mv for the externalsrc relocation, and pass the empty-directory find command as an argv list. The first cpio copy pass continues to ignore failures as before since some inputs are expected to fail. The symlink fixup copy still reports cpio failures. Signed-off-by: Anders Heimer --- meta/lib/oe/package.py | 70 +++++++++++++++++++++++++++++------------- 1 file changed, 48 insertions(+), 22 deletions(-) diff --git a/meta/lib/oe/package.py b/meta/lib/oe/package.py index c375acc124..c4ad364b64 100644 --- a/meta/lib/oe/package.py +++ b/meta/lib/oe/package.py @@ -1017,26 +1017,48 @@ def copydebugsources(debugsrcdir, sources, d): bb.utils.mkdirhier(basepath) cpath.updatecache(basepath) - for pmap in prefixmap: - # Ignore files from the recipe sysroots (target and native) - cmd = "LC_ALL=C ; sort -z -u '%s' | egrep -v -z '((|)$|/.*recipe-sysroot.*/)' | " % sourcefile - # We need to ignore files that are not actually ours - # we do this by only paying attention to items from this package - cmd += "fgrep -zw '%s' | " % prefixmap[pmap] - # Remove prefix in the source paths - cmd += "sed 's#%s/##g' | " % (prefixmap[pmap]) - cmd += "(cd '%s' ; cpio -pd0mlLu --no-preserve-owner '%s%s' 2>/dev/null)" % (pmap, dvar, prefixmap[pmap]) + # Ignore files from the recipe sysroots (target and native), and + # compiler internal entries. + with open(sourcefile, "rb") as f: + sourcepaths = sorted({path for path in f.read().split(b"\0") + if path + and not path.endswith((b"", b"")) + and b"recipe-sysroot" not in os.path.dirname(path)}) + + for pmap, prefix in prefixmap.items(): + dstroot = dvar + prefix + prefix_slash = os.fsencode(prefix) + b"/" + relpaths = [path[len(prefix_slash):] + for path in sourcepaths + if path.startswith(prefix_slash)] + + if relpaths: + subprocess.run(["cpio", "-pd0mlLu", "--no-preserve-owner", dstroot], + input=b"\0".join(relpaths) + b"\0", + cwd=pmap, stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, check=False) - try: - subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT) - except subprocess.CalledProcessError: - # Can "fail" if internal headers/transient sources are attempted - pass # cpio seems to have a bug with -lL together and symbolic links are just copied, not dereferenced. # Work around this by manually finding and copying any symbolic links that made it through. - cmd = "find %s%s -type l -print0 -delete | sed s#%s%s/##g | (cd '%s' ; cpio -pd0mL --no-preserve-owner '%s%s')" % \ - (dvar, prefixmap[pmap], dvar, prefixmap[pmap], pmap, dvar, prefixmap[pmap]) - subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT) + symlinks = [] + for root, dirs, files in os.walk(dstroot, topdown=True, followlinks=False): + for name in dirs[:]: + path = os.path.join(root, name) + if os.path.islink(path): + symlinks.append(os.fsencode(os.path.relpath(path, dstroot))) + os.unlink(path) + dirs.remove(name) + + for name in files: + path = os.path.join(root, name) + if os.path.islink(path): + symlinks.append(os.fsencode(os.path.relpath(path, dstroot))) + os.unlink(path) + + if symlinks: + subprocess.check_output(["cpio", "-pd0mL", "--no-preserve-owner", dstroot], + input=b"\0".join(sorted(symlinks)) + b"\0", + cwd=pmap, stderr=subprocess.STDOUT) # debugsources.list may be polluted from the host if we used externalsrc, # cpio uses copy-pass and may have just created a directory structure @@ -1046,13 +1068,17 @@ def copydebugsources(debugsrcdir, sources, d): # Same check as above for externalsrc if workdir not in sdir: - if os.path.exists(dvar + debugsrcdir + sdir): - cmd = "mv %s%s%s/* %s%s" % (dvar, debugsrcdir, sdir, dvar,debugsrcdir) - subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT) + srcdir = dvar + debugsrcdir + sdir + dstdir = dvar + debugsrcdir + if os.path.exists(srcdir): + entries = sorted(glob.glob(os.path.join(glob.escape(srcdir), "*"))) + if entries: + subprocess.check_output(["mv", "--"] + entries + [dstdir], + stderr=subprocess.STDOUT) # The copy by cpio may have resulted in some empty directories! Remove these - cmd = "find %s%s -empty -type d -delete" % (dvar, debugsrcdir) - subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT) + cmd = ["find", dvar + debugsrcdir, "-empty", "-type", "d", "-delete"] + subprocess.check_output(cmd, stderr=subprocess.STDOUT) # Also remove debugsrcdir if its empty for p in nosuchdir[::-1]: From patchwork Thu Jun 18 07:19:08 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anders Heimer X-Patchwork-Id: 90408 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id CBBDDCD98F6 for ; Thu, 18 Jun 2026 07:19:22 +0000 (UTC) Received: from PA4PR04CU001.outbound.protection.outlook.com (PA4PR04CU001.outbound.protection.outlook.com [40.107.162.28]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.14004.1781767159077588388 for ; Thu, 18 Jun 2026 00:19:19 -0700 Authentication-Results: mx.groups.io; dkim=fail reason="dkim: body hash did not verify" header.i=@est.tech header.s=selector1 header.b=e528wCeM; spf=pass (domain: est.tech, ip: 40.107.162.28, mailfrom: anders.heimer@est.tech) ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=Q07cdIFyy+mYVWna3/xJ+2asdhiXT0vmoCWVwK4cgicyjMLY1UzV3mGI8prLloxKA4OPtVaIoaUQofPhrSc3fBE10coEUDtP5VCgUJ5MY0qZdyc5WNXNPPiVhpQ1vDMbdThi/F5VekHpVMKhH8z6144p42Jpdj1izJayPfQYyXa6kX9WWCmAOs/P9S64Q00mNWppq1tSBp8/2VukYOD995admBOKsVL7wPFugmfSqG/oqNV5D9Y/nqZHqQKQmHpwXmCWkK8uH9w3J4pQ9hqF7t+uNWuedkPCj3ggtReWB5qHxI0tnbBsfc9imQOvwpEwiI1j5FRJPghXPCcKOd9KkQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=xbNb9p8AI56i2AXGYO3COLbbTRphiS/7WrzAqNrgI1w=; b=IdKKfp007ZxJxTRa8Sxsyes5tpMPfErqc8aSY/KmNbHRU9Vj6o1m2gtzRbqA5MyxSuUg8atugAw1fnJvL0Ke0T2pp1Kz1YHNGWnrcX4lH3liC2fGC3bTMYUNVy2PVv3Tpt3rYqOu3dXs4JQv5WFY9jLadmmDQQ43Ccxmuu5mBvpFeUQbTlS9PwVlvcpK5EzEODuzNaXhtZwE+3i6BdndKtsfMjI2TdmNLC4RDDwwt/GFuUkMz6rFzgpQ/aL79XmrgVlBKIKCnUFhZ+ZgzRkdf2aJcYh6jmX2DYxsNRpF6t5sIxZD1RKYE4vf8CJ7VD0VQ4WvJqakNeuEzFKSg3NF0A== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=est.tech; dmarc=pass action=none header.from=est.tech; dkim=pass header.d=est.tech; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=est.tech; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=xbNb9p8AI56i2AXGYO3COLbbTRphiS/7WrzAqNrgI1w=; b=e528wCeMuSJ4MeY/laOSGup1qU+xFfYnDD4W0FwE5PJbbSjiWKlQ2enooCyaTM/T2GKDIjOnmHoT25NHtOznpCKHgkmoREKMD6zKA9Ji68pIs+gsCbMn6pP59w2GyG5SI7As37sHFycZXAmdvXKI1RjbZvBFQBlVl9n72ALeuJm9U3hKzUzFkNW/Puv/7IFicstiNcSq2FQHxaZ7oUh6Ib3qlV/vJVCQWBb/WIeU/a97trNiVrcgccpsrx89uCWrAjGuUIFtmNirZegs+AJMc871fEc/uditE7AsFN73gkCiN7QXWHFAMY63RvPUP4DjAoVQpgtP1MrTXoX9VZpEpA== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=est.tech; Received: from DB9P189MB1641.EURP189.PROD.OUTLOOK.COM (2603:10a6:10:2ac::9) by DB8P189MB0840.EURP189.PROD.OUTLOOK.COM (2603:10a6:10:16f::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.139.13; Thu, 18 Jun 2026 07:19:15 +0000 Received: from DB9P189MB1641.EURP189.PROD.OUTLOOK.COM ([fe80::90da:b700:f102:5c82]) by DB9P189MB1641.EURP189.PROD.OUTLOOK.COM ([fe80::90da:b700:f102:5c82%6]) with mapi id 15.21.0139.011; Thu, 18 Jun 2026 07:19:15 +0000 From: Anders Heimer To: openembedded-core@lists.openembedded.org CC: Anders Heimer Subject: [PATCH v2 2/2] oeqa/selftest: add copydebugsources tests Date: Thu, 18 Jun 2026 09:19:08 +0200 Message-ID: <6544c23dd1abc78b8e2cfab1aab64b779a23b59f.1781766061.git.anders.heimer@est.tech> X-Mailer: git-send-email 2.43.0 In-Reply-To: References: X-ClientProxiedBy: LO4P123CA0341.GBRP123.PROD.OUTLOOK.COM (2603:10a6:600:18c::22) To DB9P189MB1641.EURP189.PROD.OUTLOOK.COM (2603:10a6:10:2ac::9) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: DB9P189MB1641:EE_|DB8P189MB0840:EE_ X-MS-Office365-Filtering-Correlation-Id: f4407b2a-439d-4ccd-b320-08decd09e714 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|376014|1800799024|23010399003|366016|11063799006|56012099006|18002099003|22082099003; X-Microsoft-Antispam-Message-Info: CXlRD4FtsdkrLtm1PMzeXX9pmotT54VfQQW8aqly9QfaCMgYtH3lMTcbcyb5UIPh6BW6Oi6wHStDd26I+eo6qE70vWL1IpZ7zM17HdpAlrwsPUbfS9vrtYkREIW4JhYVhXRq5ax498QFKUYZkFuKzp/BicuOD6djccEmW7LqW8/vqXNc2ibrjZUVHEhvF8w6/5zLskk1SOUfHQjFLuh9srAL3DyQ7j0o6QiVLi5zhKWZWELOM+OnHE+E38q4iuy4hh3jk4mkfk8NbKCui9U4iKZwUD/9YKK+POD1RCiikdIL4cof8ddeXoxMjOBcOS2Qf5oswr8S0/hvyQ6qHiyumPVx2/Oav4tNe9OgOI0jCinSpHMHW+zoq0AAklwI67j4fxfodl1Wl1FsI/XBNv0cxsTCB1uXbz6yUaaRB/J7IS2hvf36wIrwm6YLvWFRb43Nr0kHOCkLJW42TgNzL0sJWPar4HRmkxWLxkuvZAqCWaLBh8dIviKoWURXiOdQr9mVgTy9LoatHnfWYr9N3vLeQDfu7UiiyFW9FkFFut86+qD3GnXCuvyRzQYu3ius9956Mm8nByAa9pOr05vo5m1CSF/WOzR4RB5i+00xt7GocqaYmSo+Jw5u5O+SNBfM6lpcHFTW6jrW/T43keJmQUdjug3v8PWN830wAGL0XEk5/Fh9fNBRlGXQpi95jkXq/1PE X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:DB9P189MB1641.EURP189.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFS:(13230040)(376014)(1800799024)(23010399003)(366016)(11063799006)(56012099006)(18002099003)(22082099003);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: QLHBy7lAtxxjAgrsSwP819x4XMZ+cPgjkoUUbu33kDyPCUOOp28uzsLui0hjRWpCKOGhJ+VY6BX3dHEzQNr3tAvNYo7yq5KDqCo3W7ms+At9X4dgEttnUxyzlbzTVM84EYdng4D9HARm1zY5xbjTh2w8JuHHPLn/TkjhDOKgTJ8mUxTM6z6bcK6SFk/VON9mnMbXHHh6XwDP2c3IiBZ18X2gjSoZPy0s/pqR8LAKYJcCSvD6GO59MZEXANt+7lTRHQxgvL21vklu/5R0UA+4m+NOVvrPOkX59KlJntlnILZ0wcnc8plurO06f3EM0Z0wP95k9skQy1hZUko7wu/mfvPveiQAzDIWFjd0bL0XGNDlahVdxDlOJVzUNDljVJCgHqOcsY1EtKGdMGaRbDH45lEAb+NcL2Ga3zgYmG5xl4cU4BH/TH5+A5J/1TBtDj78RrEWpyJUePQtDrogdK2lQIiJ10zMEiStkjApZSFoNaSPgkF+5Llx1nBaG8QkTHxqb4syVvrnWMPxYW6NzbP1XxaAth5/su7ZqpFtEd0TX334UkwkcEn0xwAD32j7eTHyyss9IOKJzBAdrFq8nuOtNx73A6E1NreoNfq5QAOLhIHC8MSgkXks+cfTmZb3Xx3ptLjL3Xn6c6T5SXkR52ZXGhrtLGlElj2K0Rh2vzPxHWvNJ5xWpy7rv5lZ/LCr7JLPzTRcV88tIr+fVWTaPLn0lfCvM9KG/9ACNbuWWUP6ySwFc9WlPr1IP6JgZv2B6EP+2XSjoXX/he39fMfWIh5HgR8jmrH01SmvYOb2FaiO+epkDWhAedFkHCxu1bHaECLkJb7wveXbd/zEF3kFo+JLc2drCMlIX+EO3qQTUwHmI4tSWgrG88LRvF9uZ2iXsHk7nUIu9wO4T+L3PEbgEovUmxXs5lM+DV+KBzu6A5nppLfu4st7+CaccUj+y/dYEeaozzOfR14+M5VaMasLmOhsDogu9BRQmIOOt6Ds/7D8kO7KxD4Vh3H5V362PFnV4b5Z7huJB9G0W85tBNEyfl97DEoKPF7YZ1o9bHc7ccD+1x0d2hpSMdUnSznasHDBj9q0MK38AEModFka8utRg/H9Psla//qBx5s6PB719jntl57a2Jq3KPU4UM8YjTsL18iPmv9nFmY3n563JOasKXqJdQp6HQLYv1SNQ4tjDXzKqfsDFmBSDxnyYsSnlDV51eF4sGDVCeJelJnBoHfI25W25FlmrEY0B6/RMHAs55Ar4iGAWJbdmJxEDOcA5YbMWzFEMH831qsNjCEy0525xwX3XNB11lKOfMe3xLK98czVH6vkg7XKtjU6aqmwqYvU3/lOCtpo5ypYWi2c+u57tm7EtB6La2enZ+PbkRDE5o2UpX4Dl0rA2PZ/nshaqEWfQVM7F8b8mtnDraSLx+QTnQwMRi2q6N1r16dqhVUQ8nlb9jy8D6I2GiCt1vSt0H+bur/wrb3BZhp+KYFDY1Kqz9SEtFdwiug0+MaZBaUuESM8AyVZRxBT3iUwK8MwHRW0s6hzZe5A1/4vNi877k9OCH7Nd+MA2E0rpkx1/5IVO+vy9K99mHgSWV/o7lMQDdhL5vtabEf3ktxgSIznOma1WNTgyXKgb8xv4l9mxAdhVRAHlIwNTbWGtJS8Rwltpilz6BycRxiv2qSMNqTQITV8jYlYugnuFnOQvMGZx4qOKPk6su68/pDiruompo3Q81ChYebbCiyBgLpan9+vyFpmiKk1Rw== X-OriginatorOrg: est.tech X-MS-Exchange-CrossTenant-Network-Message-Id: f4407b2a-439d-4ccd-b320-08decd09e714 X-MS-Exchange-CrossTenant-AuthSource: DB9P189MB1641.EURP189.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 18 Jun 2026 07:19:14.9594 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: d2585e63-66b9-44b6-a76e-4f4b217d97fd X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: tM0WCx2cmp6IYGvLLmFKvYT+VupNmGW9VKv+D27KQlKF/MyCoSFXq0cOTpQOheIiRAeqHWmsW9tv15k895AHuA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB8P189MB0840 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Thu, 18 Jun 2026 07:19:22 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/239062 Cover multiple source-prefix mappings, recipe-sysroot and compiler entry filtering, filenames requiring safe argument handling, symlink dereferencing, tolerated cpio copy failures, empty-directory cleanup, and externalsrc relocation. Exercise paths containing spaces and glob metacharacters, leading-dash filenames, mv overwrite behavior, an empty relocation directory, and a source copy failure which leaves the prefix-specific destination uncreated. AI-Generated: Claude Opus 4.6 Signed-off-by: Anders Heimer --- meta/lib/oeqa/selftest/cases/oelib/package.py | 274 ++++++++++++++++++ 1 file changed, 274 insertions(+) create mode 100644 meta/lib/oeqa/selftest/cases/oelib/package.py diff --git a/meta/lib/oeqa/selftest/cases/oelib/package.py b/meta/lib/oeqa/selftest/cases/oelib/package.py new file mode 100644 index 0000000000..b9f9324a10 --- /dev/null +++ b/meta/lib/oeqa/selftest/cases/oelib/package.py @@ -0,0 +1,274 @@ +# +# Copyright OpenEmbedded Contributors +# +# SPDX-License-Identifier: MIT +# + +import os +import shutil +import tempfile +from unittest.case import TestCase + +from oe.package import copydebugsources + + +class FakeDataStore: + def __init__(self, values): + self.values = values + + def getVar(self, name): + return self.values.get(name) + + def expand(self, value): + for name, replacement in self.values.items(): + value = value.replace("${%s}" % name, replacement) + return value + + +class TestCopyDebugSources(TestCase): + def setUp(self): + for tool in ("cpio", "find", "mv"): + if shutil.which(tool) is None: + self.skipTest("Required tool %s not found" % tool) + + def test_copydebugsources_copies_files_and_dereferences_links(self): + with tempfile.TemporaryDirectory(prefix="oe-test-package-") as tmpdir: + source_root = os.path.join(tmpdir, "source") + second_source_root = os.path.join(tmpdir, "second-source") + workdir = os.path.join(tmpdir, "work") + pkgd = os.path.join(tmpdir, "pkgd") + debugsrcdir = "/usr/src/debug/testpkg/1.0" + second_debugsrcdir = "/usr/src/debug/secondpkg/1.0" + + os.makedirs(os.path.join(source_root, "nested")) + os.makedirs(second_source_root) + os.makedirs(workdir) + os.makedirs(pkgd) + + normal = os.path.join(source_root, "nested", "normal.c") + special = os.path.join(source_root, "nested", "name with ; spaces.c") + leading_dash = os.path.join(source_root, "nested", "-leading-dash.c") + recipe_sysroot_basename = os.path.join(source_root, "nested", + "recipe-sysroot-file.c") + internal = os.path.join(source_root, "nested", "compiler") + built_in = os.path.join(source_root, "nested", "compiler") + target = os.path.join(source_root, "nested", "target.c") + link = os.path.join(source_root, "nested", "link.c") + ignored_src = os.path.join(source_root, "recipe-sysroot", "ignored.c") + ignored_native_src = os.path.join(source_root, + "foo-recipe-sysroot-native", + "ignored.c") + second = os.path.join(second_source_root, "second.c") + + with open(normal, "w") as f: + f.write("normal\n") + with open(special, "w") as f: + f.write("special\n") + with open(leading_dash, "w") as f: + f.write("leading dash\n") + with open(recipe_sysroot_basename, "w") as f: + f.write("recipe sysroot basename\n") + with open(internal, "w") as f: + f.write("internal\n") + with open(built_in, "w") as f: + f.write("built in\n") + with open(target, "w") as f: + f.write("target\n") + os.symlink("target.c", link) + os.makedirs(os.path.dirname(ignored_src)) + with open(ignored_src, "w") as f: + f.write("ignored\n") + os.makedirs(os.path.dirname(ignored_native_src)) + with open(ignored_native_src, "w") as f: + f.write("ignored native\n") + with open(second, "w") as f: + f.write("second\n") + + empty_dir = os.path.join(pkgd, debugsrcdir.lstrip("/"), + "empty", "dir") + os.makedirs(empty_dir) + + sources = [ + os.path.join(debugsrcdir, "nested", "normal.c"), + os.path.join(debugsrcdir, "nested", "name with ; spaces.c"), + os.path.join(debugsrcdir, "nested", "-leading-dash.c"), + os.path.join(debugsrcdir, "nested", "recipe-sysroot-file.c"), + os.path.join(debugsrcdir, "nested", "compiler"), + os.path.join(debugsrcdir, "nested", "compiler"), + os.path.join(debugsrcdir, "nested", "link.c"), + os.path.join(debugsrcdir, "recipe-sysroot", "ignored.c"), + os.path.join(debugsrcdir, "foo-recipe-sysroot-native", + "ignored.c"), + os.path.join(second_debugsrcdir, "second.c"), + ] + d = FakeDataStore({ + "WORKDIR": workdir, + "PKGD": pkgd, + "STRIP": "strip", + "OBJCOPY": "objcopy", + "S": os.path.join(workdir, "source"), + "CFLAGS": ( + "-ffile-prefix-map=%s=%s " + "-ffile-prefix-map=%s=%s" + ) % ( + source_root, + debugsrcdir, + second_source_root, + second_debugsrcdir, + ), + }) + + copydebugsources(debugsrcdir, sources, d) + + copied_normal = os.path.join(pkgd, debugsrcdir.lstrip("/"), + "nested", "normal.c") + copied_special = os.path.join(pkgd, debugsrcdir.lstrip("/"), + "nested", "name with ; spaces.c") + copied_leading_dash = os.path.join(pkgd, debugsrcdir.lstrip("/"), + "nested", "-leading-dash.c") + copied_recipe_sysroot_basename = os.path.join( + pkgd, debugsrcdir.lstrip("/"), "nested", "recipe-sysroot-file.c") + copied_internal = os.path.join(pkgd, debugsrcdir.lstrip("/"), + "nested", "compiler") + copied_built_in = os.path.join(pkgd, debugsrcdir.lstrip("/"), + "nested", "compiler") + copied_link = os.path.join(pkgd, debugsrcdir.lstrip("/"), + "nested", "link.c") + copied_second = os.path.join(pkgd, second_debugsrcdir.lstrip("/"), + "second.c") + ignored = os.path.join(pkgd, debugsrcdir.lstrip("/"), + "recipe-sysroot", "ignored.c") + ignored_native = os.path.join(pkgd, debugsrcdir.lstrip("/"), + "foo-recipe-sysroot-native", + "ignored.c") + + with open(copied_normal) as f: + self.assertEqual(f.read(), "normal\n") + with open(copied_special) as f: + self.assertEqual(f.read(), "special\n") + with open(copied_leading_dash) as f: + self.assertEqual(f.read(), "leading dash\n") + with open(copied_recipe_sysroot_basename) as f: + self.assertEqual(f.read(), "recipe sysroot basename\n") + with open(copied_link) as f: + self.assertEqual(f.read(), "target\n") + with open(copied_second) as f: + self.assertEqual(f.read(), "second\n") + self.assertFalse(os.path.islink(copied_link)) + self.assertFalse(os.path.exists(copied_internal)) + self.assertFalse(os.path.exists(copied_built_in)) + self.assertFalse(os.path.exists(ignored)) + self.assertFalse(os.path.exists(ignored_native)) + self.assertFalse(os.path.exists(empty_dir)) + + def test_copydebugsources_ignores_copy_failure(self): + with tempfile.TemporaryDirectory(prefix="oe-test-package-") as tmpdir: + source_root = os.path.join(tmpdir, "source") + workdir = os.path.join(tmpdir, "work") + pkgd = os.path.join(tmpdir, "pkgd") + debugsrcdir = "/usr/src/debug/testpkg/1.0" + mapped_debugsrcdir = os.path.join(debugsrcdir, "mapped") + + os.makedirs(source_root) + os.makedirs(workdir) + os.makedirs(pkgd) + + sources = [ + os.path.join(mapped_debugsrcdir, "missing.c"), + ] + d = FakeDataStore({ + "WORKDIR": workdir, + "PKGD": pkgd, + "STRIP": "strip", + "OBJCOPY": "objcopy", + "S": os.path.join(workdir, "source"), + "CFLAGS": "-ffile-prefix-map=%s=%s" % ( + source_root, + mapped_debugsrcdir, + ), + }) + + copydebugsources(debugsrcdir, sources, d) + + self.assertFalse(os.path.exists(pkgd + mapped_debugsrcdir)) + self.assertFalse(os.path.exists(pkgd + debugsrcdir)) + + def test_copydebugsources_moves_externalsrc_relocation(self): + with tempfile.TemporaryDirectory(prefix="oe-test-package-") as tmpdir: + source_root = os.path.join(tmpdir, "external-[source]") + workdir = os.path.join(tmpdir, "work") + pkgd = os.path.join(tmpdir, "pkgd") + debugsrcdir = "/usr/src/debug/testpkg/1.0" + + os.makedirs(source_root) + os.makedirs(workdir) + os.makedirs(pkgd) + + source = os.path.join(source_root, "real.c") + with open(source, "w") as f: + f.write("real\n") + + relocation = pkgd + debugsrcdir + source_root + relocated_name = "-relocated with ; spaces.c" + os.makedirs(relocation) + with open(os.path.join(relocation, relocated_name), "w") as f: + f.write("relocated\n") + with open(os.path.join(pkgd + debugsrcdir, relocated_name), "w") as f: + f.write("old\n") + + sources = [os.path.join(debugsrcdir, "real.c")] + d = FakeDataStore({ + "WORKDIR": workdir, + "PKGD": pkgd, + "STRIP": "strip", + "OBJCOPY": "objcopy", + "S": source_root, + "CFLAGS": "-ffile-prefix-map=%s=%s" % (source_root, debugsrcdir), + }) + + copydebugsources(debugsrcdir, sources, d) + + copied_source = os.path.join(pkgd, debugsrcdir.lstrip("/"), "real.c") + moved_source = os.path.join(pkgd, debugsrcdir.lstrip("/"), relocated_name) + + with open(copied_source) as f: + self.assertEqual(f.read(), "real\n") + with open(moved_source) as f: + self.assertEqual(f.read(), "relocated\n") + self.assertFalse(os.path.exists(relocation)) + + def test_copydebugsources_ignores_empty_externalsrc_relocation(self): + with tempfile.TemporaryDirectory(prefix="oe-test-package-") as tmpdir: + source_root = os.path.join(tmpdir, "external-source") + workdir = os.path.join(tmpdir, "work") + pkgd = os.path.join(tmpdir, "pkgd") + debugsrcdir = "/usr/src/debug/testpkg/1.0" + + os.makedirs(source_root) + os.makedirs(workdir) + os.makedirs(pkgd) + + source = os.path.join(source_root, "real.c") + with open(source, "w") as f: + f.write("real\n") + + relocation = pkgd + debugsrcdir + source_root + os.makedirs(relocation) + + sources = [os.path.join(debugsrcdir, "real.c")] + d = FakeDataStore({ + "WORKDIR": workdir, + "PKGD": pkgd, + "STRIP": "strip", + "OBJCOPY": "objcopy", + "S": source_root, + "CFLAGS": "-ffile-prefix-map=%s=%s" % (source_root, debugsrcdir), + }) + + copydebugsources(debugsrcdir, sources, d) + + copied_source = os.path.join(pkgd, debugsrcdir.lstrip("/"), "real.c") + + with open(copied_source) as f: + self.assertEqual(f.read(), "real\n") + self.assertFalse(os.path.exists(relocation))