From patchwork Sun Sep 10 15:52:27 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adrian Freihofer X-Patchwork-Id: 30252 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 8A8ABEE57DF for ; Sun, 10 Sep 2023 16:19:29 +0000 (UTC) Received: from mail-wm1-f46.google.com (mail-wm1-f46.google.com [209.85.128.46]) by mx.groups.io with SMTP id smtpd.web10.39051.1694362761697020691 for ; Sun, 10 Sep 2023 09:19:22 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20221208 header.b=oPBIYxXt; spf=pass (domain: gmail.com, ip: 209.85.128.46, mailfrom: adrian.freihofer@gmail.com) Received: by mail-wm1-f46.google.com with SMTP id 5b1f17b1804b1-40078c4855fso38899675e9.3 for ; Sun, 10 Sep 2023 09:19:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1694362760; x=1694967560; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=rUlTsoCRb7c61ci7ZVsjEUWCfwa7t3TQHbk7FZjqxn4=; b=oPBIYxXtZlHBAvupd6Kf18F2PAU7OgrYK1suIXZfr6Ta8ZbdBzj015Pff1qsn8vbFz 956aITzhDt9b5ce9yn7xqMip0AE6BroxsQxNUdSGQVCs//nT0jN3jNVI0hJikiQhDs4V /nXWxqOuOJXahLzkwVFzPkzTlP3sBLvTsFbrMUOhXVE3hYbNlqTBkn5GETDWKTUQGDQm PA0kJNEYOI4cHcUiYM/6QskxtlnQZ+0Pk/mDyR8R7WyIERGUHHurf5vA14kPsSbQGU46 tMkptKSU5C10+JtHOKXxKNrRwLDjJxRGBUm2qLvH+59VeIUHhmJZFuzJWkt5jGtP2dYb GP6A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1694362760; x=1694967560; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=rUlTsoCRb7c61ci7ZVsjEUWCfwa7t3TQHbk7FZjqxn4=; b=YJk14yMk+kq7cK4+dZCg1DxeCMC7JOMYaf94NsibaQeIlSKsj9Z3rY8NkNizqfNknX 6kPsKXBeFFsB41+byD7Q+2/QroVVsi97R1rNQJkNAowcElt3AnxKKSr53gmIsfAycujH RAnjlxRgnPkmqrigQxSCf/zhw6oDkARXxFJDKW7u+/d4IcYQANMYj9+sY7/NUPR1r9+U pb/pw4Z6FpH/P7pND3h5VCjtb+IdyJ0/fn4kcIGiM7jsqrAxv2oEcQSFy5K4y085aW4J 6rWYoxvJLcB7Lz3ZZb4krNQdQvGPgpSTko/KNmxu//gvTU2Cl6ivr4KI/B12+QISf4PY 40MA== X-Gm-Message-State: AOJu0YwzZSqhSR19z29lSQnCDkhB0bPE0PYFCfj/83gHZYsJ1h/4KY9s kxE90mTMatd6DaXGTQSGHKxPNB/Jycs= X-Google-Smtp-Source: AGHT+IE/Mpok2TS4WR3Pg+00laHo4iVFcGkP/RqIWVMB86u4ZumFG9JOp/TJlwv/IKD/JAZW83yMpA== X-Received: by 2002:a7b:c459:0:b0:402:a464:1a20 with SMTP id l25-20020a7bc459000000b00402a4641a20mr6295468wmi.33.1694362759679; Sun, 10 Sep 2023 09:19:19 -0700 (PDT) Received: from t14s-af.fritz.box ([2a02:169:59a6:0:dcf2:2f65:9442:83f]) by smtp.gmail.com with ESMTPSA id o12-20020a5d408c000000b003142ea7a661sm7605431wrp.21.2023.09.10.09.19.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 Sep 2023 09:19:19 -0700 (PDT) From: Adrian Freihofer X-Google-Original-From: Adrian Freihofer To: openembedded-core@lists.openembedded.org Cc: Adrian Freihofer Subject: [OE-core][PATCH v6 01/12] vscode: add minimal configuration Date: Sun, 10 Sep 2023 17:52:27 +0200 Message-ID: <20230910161850.4032227-2-adrian.freihofer@siemens.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230910161850.4032227-1-adrian.freihofer@siemens.com> References: <20230910161850.4032227-1-adrian.freihofer@siemens.com> MIME-Version: 1.0 List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Sun, 10 Sep 2023 16:19:29 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/187459 It is essential to configure VSCode indexer plugins to ignore the build folder of bitbake. Otherwise, the indexer plugins run with 100% CPU load until an OOM exception occurs. In practice, this makes VSCode more or less unusable for working with Yocto until a file like the one added by this commit is deployed before VSCode starts. From the user's point of view, it is not obvious why the system runs at 100% CPU load and eventually crashes. It is even more misleading that VSCode starts the indexers immediately, but does not stop or reconfigure them when the ignore list is updated. In practice, this means that every time the ignore list is changed, VSCode immediately starts indexing the build folder until the OOM exception stops it. Depending on the system's OOM handler, the entire build machine may crash. Particularly annoying is the Python plugin that ignores the general ignore list and requires an extra ignore section. The settings are suitable for workflows like bitbake, devtool modify, devtool reset. The settings are not intended to work on the source code of a recipe. It is assumed that a separate instance of VSCode is used per workspace folder. These per workspace instances can have different settings depending on the details of the sources that come with the recipe. The new devtool ide plugin will generate settings to match this. Signed-off-by: Adrian Freihofer --- .gitignore | 2 ++ .vscode/settings.json | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 .vscode/settings.json diff --git a/.gitignore b/.gitignore index 8f48d452dab..f6ce090b5fc 100644 --- a/.gitignore +++ b/.gitignore @@ -36,3 +36,5 @@ _toaster_clones/ downloads/ sstate-cache/ toaster.sqlite +.vscode/ +vscode-bitbake-build/ diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000000..517a86d1bfa --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,32 @@ +{ + "files.watcherExclude": { + "**/.git/**": true, + "**/cache/**": true, + "**/tmp*/**": true, + "**/downloads/**": true, + "**/sstate-cache/**": true, + "**/vscode-bitbake-build/**": true, + "**/workspace/sources/**": true, + "**/workspace/attic/**": true + }, + "files.exclude": { + "**/.git/**": true, + "**/cache/**": true, + "**/tmp*/**": true, + "**/downloads/**": true, + "**/sstate-cache/**": true, + "**/vscode-bitbake-build/**": true, + "**/workspace/sources/**": true, + "**/workspace/attic/**": true + }, + "python.analysis.exclude": [ + "**/.git/**", + "**/cache/**", + "**/tmp*/**", + "**/downloads/**", + "**/sstate-cache/**", + "**/vscode-bitbake-build/**", + "**/workspace/sources/**", + "**/workspace/attic/**" + ] +} From patchwork Sun Sep 10 15:52:28 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adrian Freihofer X-Patchwork-Id: 30253 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 9EA33EE49A4 for ; Sun, 10 Sep 2023 16:19:29 +0000 (UTC) Received: from mail-wm1-f42.google.com (mail-wm1-f42.google.com [209.85.128.42]) by mx.groups.io with SMTP id smtpd.web10.39052.1694362762488749539 for ; Sun, 10 Sep 2023 09:19:22 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20221208 header.b=ZMbZfBZm; spf=pass (domain: gmail.com, ip: 209.85.128.42, mailfrom: adrian.freihofer@gmail.com) Received: by mail-wm1-f42.google.com with SMTP id 5b1f17b1804b1-403012f27e1so14704985e9.1 for ; Sun, 10 Sep 2023 09:19:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1694362760; x=1694967560; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=MND5e5KB4OZVVC644V91vwSuJuyFeLqIvR4uWSLBv8M=; b=ZMbZfBZmnwW9Hzgc2tNVkT2AmUYYYf6o4Y6rvhigBaneGZT1EK4+SCAzjDxan570r/ eApfk6vVMHAO9vRCRrtwUEgke5fni6504PPu+9sLLdkkbsGLbCvLp4eACCMBmkO8HX1W y17y5HblSQe0Wgo3iZKMemIQa31fEYraLAnuPmMSwsqEIohIazp67M+eVmnNbCeCARzY JrbvYgmwjjLO5k2Hggr5+2y8Gcuj/5wSerFaIMF+k0nYHj2KbCmInitkFjSMyMe7ACRU bF1UhV8x3DYqPteag9xW6Uoe8V/YbVu8/12xy05JYyuY68NVcqbaYWCQxygQW6jqlZoo 1sFg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1694362760; x=1694967560; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=MND5e5KB4OZVVC644V91vwSuJuyFeLqIvR4uWSLBv8M=; b=Zezray+pUW//MNbZsO0gFc+1XjkaYAJW6k5lsAk4YuJOydkldYBVGu71c3xM01c5tt 3SCrZ6yVC7RJl7Va8ODt/i9LkwbzIeTs3wKGwWmCZVGsmfCzDmzLWLHPDaZmpfZ5eTio 4W8Z6T8IfcBXLA/8TAb3B6DhG3kxh8row/qbQWEj/gENUI5Br9u1UbhGtYTMZLCeMz// Yn7LG8JwLqgKewOxw2dqudpWPwZDikvEo32l6E7d97yNHMavNseakw4x5KX1RjHQX2oA /UglG0dkad7URgxA6sDcsdrYx8pjhdqAlxWCTtEB8oDcCQyJZN4uZxCVVpp6yK2NkOc3 a2Wg== X-Gm-Message-State: AOJu0YyjbM5gzqCu4AmFGla/PAPfrLoKh5fKNu8XbV0/b7tAukAEE6T+ jZhWJ2nGyQ7qJxPb+dlQPxzl1E8j1eI= X-Google-Smtp-Source: AGHT+IFKqgZrEpch04uvYpKubASpAN4LOlVQQZwEItbIqvr5JdXknWgEtCXGMgzBbX67VWCyY8MzsA== X-Received: by 2002:a7b:ce0a:0:b0:401:d803:6250 with SMTP id m10-20020a7bce0a000000b00401d8036250mr6381898wmc.5.1694362760445; Sun, 10 Sep 2023 09:19:20 -0700 (PDT) Received: from t14s-af.fritz.box ([2a02:169:59a6:0:dcf2:2f65:9442:83f]) by smtp.gmail.com with ESMTPSA id o12-20020a5d408c000000b003142ea7a661sm7605431wrp.21.2023.09.10.09.19.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 Sep 2023 09:19:20 -0700 (PDT) From: Adrian Freihofer X-Google-Original-From: Adrian Freihofer To: openembedded-core@lists.openembedded.org Cc: Adrian Freihofer Subject: [OE-core][PATCH v6 02/12] cmake.bbclass: support qemu Date: Sun, 10 Sep 2023 17:52:28 +0200 Message-ID: <20230910161850.4032227-3-adrian.freihofer@siemens.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230910161850.4032227-1-adrian.freihofer@siemens.com> References: <20230910161850.4032227-1-adrian.freihofer@siemens.com> MIME-Version: 1.0 List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Sun, 10 Sep 2023 16:19:29 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/187460 Define the CMAKE_CROSSCOMPILING_EMULATOR variable similar to what the meson bbclass does. This allows for example to execute cross compilied unit tests on the build machine. CMAKE_CROSSCOMPILING_EMULATOR is a semi colon separated list of paramters which could directly handle the -L and the -E parameters. Creating a wrapper script is not absolutely mandatory. But anyway lets do it similar to what the meson.bbclass does and also disable pseudo. Signed-off-by: Adrian Freihofer --- meta/classes-recipe/cmake.bbclass | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/meta/classes-recipe/cmake.bbclass b/meta/classes-recipe/cmake.bbclass index 41748b08207..68b4e83bbe8 100644 --- a/meta/classes-recipe/cmake.bbclass +++ b/meta/classes-recipe/cmake.bbclass @@ -4,6 +4,13 @@ # SPDX-License-Identifier: MIT # +inherit qemu + +EXEWRAPPER_ENABLED:class-native = "False" +EXEWRAPPER_ENABLED:class-nativesdk = "False" +EXEWRAPPER_ENABLED ?= "${@bb.utils.contains('MACHINE_FEATURES', 'qemu-usermode', 'True', 'False', d)}" +DEPENDS:append = "${@' qemu-native' if d.getVar('EXEWRAPPER_ENABLED') == 'True' else ''}" + # Path to the CMake file to process. OECMAKE_SOURCEPATH ??= "${S}" @@ -156,6 +163,20 @@ EOF addtask generate_toolchain_file after do_patch before do_configure +cmake_do_generate_toolchain_file:append:class-target() { + if [ "${EXEWRAPPER_ENABLED}" = "True" ]; then + # Write out a qemu wrapper that will be used as exe_wrapper so that camake + # can run target helper binaries through that. This also allows to execute ctest. + qemu_binary="${@qemu_wrapper_cmdline(d, '${STAGING_DIR_HOST}', ['${STAGING_DIR_HOST}/${libdir}','${STAGING_DIR_HOST}/${base_libdir}'])}" + echo "#!/bin/sh" > "${WORKDIR}/cmake-qemuwrapper" + echo "$qemu_binary \"\$@\"" >> "${WORKDIR}/cmake-qemuwrapper" + chmod +x "${WORKDIR}/cmake-qemuwrapper" + echo "set( CMAKE_CROSSCOMPILING_EMULATOR ${WORKDIR}/cmake-qemuwrapper)" \ + >> ${WORKDIR}/toolchain.cmake + fi +} + + CONFIGURE_FILES = "CMakeLists.txt" do_configure[cleandirs] = "${@d.getVar('B') if d.getVar('S') != d.getVar('B') else ''}" From patchwork Sun Sep 10 15:52:29 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adrian Freihofer X-Patchwork-Id: 30258 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 A05F1EEB581 for ; Sun, 10 Sep 2023 16:19:29 +0000 (UTC) Received: from mail-wr1-f42.google.com (mail-wr1-f42.google.com [209.85.221.42]) by mx.groups.io with SMTP id smtpd.web11.39124.1694362763727413488 for ; Sun, 10 Sep 2023 09:19:24 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20221208 header.b=OQhqAwKN; spf=pass (domain: gmail.com, ip: 209.85.221.42, mailfrom: adrian.freihofer@gmail.com) Received: by mail-wr1-f42.google.com with SMTP id ffacd0b85a97d-31ad779e6b3so3631357f8f.2 for ; Sun, 10 Sep 2023 09:19:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1694362762; x=1694967562; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=WbP3FzRf7OkH8/a1cCRReLeQdZU4BRcOP/pO5az/dPg=; b=OQhqAwKNdBm0/nvyVEa60QIEHCgR8KUJOR9D1+EMG9ynFoldnQF/ZW0sDUstXmQowL p6CEoqbjAUbWGG0VTfZjBvMqCvqgmzRutKdsl4k/ulhkbNmhIU8ciymmxgB5Rusj2Jjv /5IZrsnaC08KGXHoKCanUXNVnDCSpOJ3lNiNQaukGABalIvMu23XEt7B67mV+xL5TOa+ My4FgEZSxJtKTP4oinLTpx2AdOm6N82B5VDVuuGF3JyqVAEAcF+e6l86SrBoeWUi3LIT q/oS7ywq4UZ2uF2FgBoS5dy5ViG/8juVyN5WkqYKK1jGy/uyDLY5oIiUd7dSOG8XX2Oz 4syA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1694362762; x=1694967562; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=WbP3FzRf7OkH8/a1cCRReLeQdZU4BRcOP/pO5az/dPg=; b=pO9vzKR4ZmNxDVH8xtJEXieg5GRFfA1TQAkzdSb1LO0rKXzIkpGaGslLPZPZHuO4t6 z45f3dgN3Tpch9nayVA9/CXtmTr4sfAQ9Q4PZEvREoe6iYvvZAkDXOSe5jxZ1mJRitN7 BP1bJTKbCfqwZRnA54Y4s2iI6fhR5AxuIzcD0SeInPnN9J6OHURlA1EqJhfZZQoaTUuE 7db00wSlfAQXyq+t0t2Jav1DDm0/YtLSg2WVhIMBTpmz326Se53/EArhpWQMWzmu7wR7 G6uAncaSPDcNeUVPGIQ/xJU4b2a6RIrp3qwYPQ7V+kY7cro8S6HsoSKhpy3iJpXI3GCY w9Ag== X-Gm-Message-State: AOJu0YxxKV6Z02IyXnozCfwnmUPK27ovAdPqkoQPl/jlMo5PyXxt0RNE cRq6Y8FweocLVHHrOk87deSHK4MNQHQ= X-Google-Smtp-Source: AGHT+IHxY4u8126tkx0ZKoTZwUz/roBAcDB1NbKxilBxlLbtSvp5Q5R/L2zLWyx0/X4K5se0d47/FQ== X-Received: by 2002:a5d:4486:0:b0:317:5b1b:1a40 with SMTP id j6-20020a5d4486000000b003175b1b1a40mr6344803wrq.49.1694362761405; Sun, 10 Sep 2023 09:19:21 -0700 (PDT) Received: from t14s-af.fritz.box ([2a02:169:59a6:0:dcf2:2f65:9442:83f]) by smtp.gmail.com with ESMTPSA id o12-20020a5d408c000000b003142ea7a661sm7605431wrp.21.2023.09.10.09.19.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 Sep 2023 09:19:21 -0700 (PDT) From: Adrian Freihofer X-Google-Original-From: Adrian Freihofer To: openembedded-core@lists.openembedded.org Cc: Adrian Freihofer Subject: [OE-core][PATCH v6 03/12] devtool: new ide plugin Date: Sun, 10 Sep 2023 17:52:29 +0200 Message-ID: <20230910161850.4032227-4-adrian.freihofer@siemens.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230910161850.4032227-1-adrian.freihofer@siemens.com> References: <20230910161850.4032227-1-adrian.freihofer@siemens.com> MIME-Version: 1.0 List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Sun, 10 Sep 2023 16:19:29 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/187461 The new devtool ide plugin configures an IDE to work with the eSDK. With this initial implementation VSCode is the default IDE. The plugin works for recipes inheriting the cmake or the meson bbclass. Support for more programming languages and build tools may be added in the future. Using the plugin in recipe modes: $ devtool modify a-recipe $ devtool ide a-recipe a-image $ code "$BUILDDIR/workspace/sources/a-recipe" Work in VSCode, after installing the proposed plugins Using the plugin without a recipe $ devtool ide none a-image vscode where/the/sources/are Use the cross tool-chain which is provided as a cmake-kit. The goal of this implementation is to create a configuration for VSCode (or other IDEs) that allows to work on the code of a recipe completely independent from bitbake. bitbake is only called if the configuration or the whole SDK has to be regenerated. But bitbake should not need to be called while working in the IDE. This has two major advantages over calling devtool build from the IDE: - The IDE provides plugins for integration with cmake, for example. These features are usable, which would not be the case if bitbake or devtool are called from within the IDE. - It is much faster. Signed-off-by: Adrian Freihofer --- scripts/lib/devtool/ide.py | 1190 ++++++++++++++++++++++++++++++++++++ 1 file changed, 1190 insertions(+) create mode 100755 scripts/lib/devtool/ide.py diff --git a/scripts/lib/devtool/ide.py b/scripts/lib/devtool/ide.py new file mode 100755 index 00000000000..7c7040232c4 --- /dev/null +++ b/scripts/lib/devtool/ide.py @@ -0,0 +1,1190 @@ +#! /usr/bin/env python3 +# +# Copyright (C) 2023 Siemens AG +# +# SPDX-License-Identifier: GPL-2.0-only +# + +"""Devtool ide plugin""" + +import os +import stat +import logging +import json +import re +import shutil +from argparse import RawTextHelpFormatter +from enum import IntEnum, auto + +import bb +from devtool import exec_build_env_command, setup_tinfoil, check_workspace_recipe, DevtoolError, parse_recipe +from devtool.standard import get_real_srctree + +SHARED_SYSROOT_RECIPES = ['none', 'meta-ide-support', 'build-sysroots'] +SUPPORTED_IDES = ['code', 'none'] + +logger = logging.getLogger('devtool') + + +class TargetDevice: + """SSH remote login parameters""" + + def __init__(self, args): + self.extraoptions = '' + if args.no_host_check: + self.extraoptions += '-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no' + self.ssh_sshexec = 'ssh' + if args.ssh_exec: + self.ssh_sshexec = args.ssh_exec + self.ssh_port = '' + if args.port: + self.ssh_port = "-p %s" % args.port + if args.key: + self.extraoptions += ' -i %s' % args.key + + self.target = args.target + target_sp = args.target.split('@') + if len(target_sp) == 1: + self.login = "" + self.host = target_sp[0] + elif len(target_sp) == 2: + self.login = target_sp[0] + self.host = target_sp[1] + else: + logger.error("Invalid target argument: %s" % args.target) + + +class RecipeNative: + def __init__(self, name, target_arch=None): + self.name = name + self.target_arch = target_arch + self.bootstrap_tasks = [self.name + ':do_addto_recipe_sysroot'] + self.staging_bindir_native = None + self.target_sys = None + self.__native_bin = None + + def initialize(self, config, workspace, tinfoil): + recipe_d = parse_recipe( + config, tinfoil, self.name, appends=True, filter_workspace=False) + if not recipe_d: + raise DevtoolError("Parsing %s recipe failed" % self.name) + self.staging_bindir_native = os.path.realpath( + recipe_d.getVar('STAGING_BINDIR_NATIVE')) + self.target_sys = recipe_d.getVar('TARGET_SYS') + + @property + def native_bin(self): + if not self.__native_bin: + raise DevtoolError("native binary name is not defined.") + return self.__native_bin + + +class RecipeGdbCross(RecipeNative): + def __init__(self, args, target_arch, target_device, gdbserver_multi=True): + super().__init__('gdb-cross-' + target_arch, target_arch) + self.target_device = target_device + self.gdb = None + self.gdbserver_port_next = int(args.gdbserver_port_start) + self.gdbserver_multi = gdbserver_multi + self.config_db = {} + + def initialize(self, config, workspace, tinfoil): + super().initialize(config, workspace, tinfoil) + gdb_bin = self.target_sys + '-gdb' + gdb_path = os.path.join( + self.staging_bindir_native, self.target_sys, gdb_bin) + self.gdb = gdb_path + + @property + def host(self): + return self.target_device.host + + def __gdbserver_start_cmd(self, binary, port): + if self.gdbserver_multi: + gdbserver_cmd = "/usr/bin/gdbserver --multi :%s" % ( + port) + else: + gdbserver_cmd = "/usr/bin/gdbserver --once :%s %s" % ( + port, binary) + return "%s %s %s %s 'sh -c \"%s\"'" % ( + self.target_device.ssh_sshexec, self.target_device.ssh_port, self.target_device.extraoptions, self.target_device.target, gdbserver_cmd) + + def setup_gdbserver_config(self, binary, script_dir): + if binary in self.config_db: + raise DevtoolError( + "gdbserver config for binary %s is already generated" % binary) + + port = self.gdbserver_port_next + self.gdbserver_port_next += 1 + config_entry = { + "port": port, + } + if script_dir: + cmd_lines = ['#!/bin/sh'] + cmd_lines.append(self.__gdbserver_start_cmd(binary, port)) + binary_name_pretty = binary.replace(os.sep, '-') + start_script_name = 'gdbserver_start_%d_%s' % ( + port, binary_name_pretty) + if self.gdbserver_multi: + start_script_name += "_m" + start_script_file = os.path.join(script_dir, start_script_name) + config_entry['gdbserver_start_script'] = start_script_file + config_entry['pretty_id'] = 'gdbserver start %d %s' % ( + port, binary) + + bb.utils.mkdirhier(script_dir) + with open(start_script_file, 'w') as script_f: + script_f.write(os.linesep.join(cmd_lines)) + script_f.write(os.linesep) + st = os.stat(start_script_file) + os.chmod(start_script_file, st.st_mode | stat.S_IEXEC) + + self.config_db[binary] = config_entry + return config_entry + + def get_gdbserver_start_scripts(self): + for conf in self.config_db.values(): + yield (conf['pretty_id'], conf['gdbserver_start_script']) + + def get_gdbserver_pretty_id(self, binary): + return self.config_db[binary]['pretty_id'] + + def get_gdbserver_port(self, binary): + return self.config_db[binary]['port'] + + def get_gdbserver_start_script(self, binary): + return self.config_db[binary]['gdbserver_start_script'] + + +class RecipeImage: + """Handle some image recipe related properties""" + + def __init__(self, name): + self.combine_dbg_image = False + self.debuginfod = False + self.name = name + self.package_debug_split_style = None + self.rootfs = None + self.__rootfs_dbg = None + self.bootstrap_tasks = [self.name + ':do_build'] + + def initialize(self, config, tinfoil): + image_d = parse_recipe( + config, tinfoil, self.name, appends=True, filter_workspace=False) + if not image_d: + raise DevtoolError( + "Parsing image recipe %s failed" % self.name) + if 'debuginfod' in image_d.getVar('DISTRO_FEATURES').split(): + # image_config.debuginfod = True + logger.warning("Support for debuginfod is not implemented yet.") + + self.package_debug_split_style = image_d.getVar( + 'PACKAGE_DEBUG_SPLIT_STYLE') + + workdir = image_d.getVar('WORKDIR') + self.rootfs = os.path.join(workdir, 'rootfs') + if image_d.getVar('IMAGE_GEN_DEBUGFS') == "1": + self.__rootfs_dbg = os.path.join(workdir, 'rootfs-dbg') + + self.combine_dbg_image = bb.data.inherits_class( + 'image-combined-dbg', image_d) + + @property + def debug_support(self): + return bool(self.debuginfod or self.rootfs_dbg) + + @property + def rootfs_dbg(self): + if self.__rootfs_dbg and os.path.isdir(self.__rootfs_dbg): + return self.__rootfs_dbg + return None + + def solib_search_path_rootfs(self): + """Search for folders with shared libraries in the rootfs and rootfs-dbg + + This is based on the assumption that the PACKAGE_DEBUG_SPLIT_STYLE variable from the image + is the global setting which is used by most packages. Even if this variable does not seem + to make sense in the image context. + """ + rootfs_solib_search_path = [] + rootfs_dbg_solib_search_path = [] + if self.package_debug_split_style in ['debug-with-srcpkg', '.debug']: + if self.combine_dbg_image: + rootfs_dbg_solib_search_path = [ + "/lib", "/lib/.debug", "/usr/lib", "/usr/lib/.debug"] + else: + logger.warn( + 'Adding IMAGE_CLASSES += "image-combined-dbg" offers better remote debugging experience.') + rootfs_solib_search_path = [ + "/lib", "/usr/lib"] + rootfs_dbg_solib_search_path = [ + "/lib/.debug", "/usr/lib/.debug"] + elif self.package_debug_split_style == 'debug-file-directory': + rootfs_dbg_solib_search_path = ["/usr/lib/debug"] + else: + logger.warning( + "Cannot find solib search path for a rootfs built with PACKAGE_DEBUG_SPLIT_STYLE=%s." % self.package_debug_split_style) + + sym_dirs = [] + for dbgdir in rootfs_solib_search_path: + sym_dirs.append(os.path.join( + self.rootfs, dbgdir.lstrip('/'))) + for dbgdir in rootfs_dbg_solib_search_path: + sym_dirs.append(os.path.join( + self.rootfs_dbg, dbgdir.lstrip('/'))) + + return sym_dirs + + +class RecipeMetaIdeSupport: + """Handle some meta-ide-support recipe related properties""" + + def __init__(self): + self.bootstrap_tasks = ['meta-ide-support:do_build'] + self.topdir = None + self.datadir = None + self.deploy_dir_image = None + self.build_sys = None + # From toolchain-scripts + self.real_multimach_target_sys = None + + def initialize(self, config, tinfoil): + meta_ide_support_d = parse_recipe( + config, tinfoil, 'meta-ide-support', appends=True, filter_workspace=False) + if not meta_ide_support_d: + raise DevtoolError("Parsing meta-ide-support recipe failed") + + self.topdir = meta_ide_support_d.getVar('TOPDIR') + self.datadir = meta_ide_support_d.getVar('datadir') + self.deploy_dir_image = meta_ide_support_d.getVar( + 'DEPLOY_DIR_IMAGE') + self.build_sys = meta_ide_support_d.getVar('BUILD_SYS') + self.real_multimach_target_sys = meta_ide_support_d.getVar( + 'REAL_MULTIMACH_TARGET_SYS') + + +class RecipeBuildSysroots: + def __init__(self): + self.standalone_sysroot = None + self.standalone_sysroot_native = None + self.bootstrap_tasks = ['build-sysroots:do_build'] + + def initialize(self, config, tinfoil): + build_sysroots_d = parse_recipe( + config, tinfoil, 'build-sysroots', appends=True, filter_workspace=False) + if not build_sysroots_d: + raise DevtoolError("Parsing build-sysroots recipe failed") + self.standalone_sysroot = build_sysroots_d.getVar( + 'STANDALONE_SYSROOT') + self.standalone_sysroot_native = build_sysroots_d.getVar( + 'STANDALONE_SYSROOT_NATIVE') + + +class SharedSysrootsEnv: + def __init__(self): + self.ide_support = None + self.build_sysroots = None + + def initialize(self, ide_support, build_sysroots): + self.ide_support = ide_support + self.build_sysroots = build_sysroots + + def __vscode_update_kits(self): + """Expose the toolchain of the dSDK""" + datadir = self.ide_support.datadir + deploy_dir_image = self.ide_support.deploy_dir_image + real_multimach_target_sys = self.ide_support.real_multimach_target_sys + standalone_sysroot_native = self.build_sysroots.standalone_sysroot_native + vscode_ws_path = os.path.join( + os.environ['HOME'], '.local', 'share', 'CMakeTools') + cmake_kits_path = os.path.join(vscode_ws_path, 'cmake-tools-kits.json') + oecmake_generator = "Ninja" + env_script = os.path.join( + deploy_dir_image, 'environment-setup-' + real_multimach_target_sys) + + logger.info("updating %s" % cmake_kits_path) + + if not os.path.isdir(vscode_ws_path): + os.makedirs(vscode_ws_path) + cmake_kits_old = [] + if os.path.exists(cmake_kits_path): + with open(cmake_kits_path, 'r', encoding='utf-8') as cmake_kits_file: + cmake_kits_old = json.load(cmake_kits_file) + cmake_kits = cmake_kits_old.copy() + + cmake_kit_new = { + "name": "OE " + real_multimach_target_sys, + "environmentSetupScript": env_script, + "toolchainFile": standalone_sysroot_native + datadir + "/cmake/OEToolchainConfig.cmake", + "preferredGenerator": { + "name": oecmake_generator + } + } + + def merge_kit(cmake_kits, cmake_kit_new): + i = 0 + while i < len(cmake_kits): + if 'environmentSetupScript' in cmake_kits[i] and \ + cmake_kits[i]['environmentSetupScript'] == cmake_kit_new['environmentSetupScript']: + cmake_kits[i] = cmake_kit_new + return + i += 1 + cmake_kits.append(cmake_kit_new) + merge_kit(cmake_kits, cmake_kit_new) + + if cmake_kits != cmake_kits_old: + bb.note("Updating: %s" % cmake_kits_path) + with open(cmake_kits_path, 'w', encoding='utf-8') as cmake_kits_file: + json.dump(cmake_kits, cmake_kits_file, indent=4) + + def setup_ide(self, args): + if args.ide == 'code': + self.__vscode_update_kits() + + +class BuildTool(IntEnum): + UNDEFINED = auto() + CMAKE = auto() + MESON = auto() + + +class RecipeModified: + + def __init__(self, name): + self.name = name + self.bootstrap_tasks = [name + ':do_install'] + # workspace + self.real_srctree = None + self.srctree = None + self.temp_dir = None + self.bbappend = None + # recipe variables from d.getVar + self.b = None + self.bpn = None + self.d = None + self.fakerootcmd = None + self.fakerootenv = None + self.package_arch = None + self.path = None + self.recipe_sysroot = None + self.recipe_sysroot_native = None + self.staging_incdir = None + self.target_arch = None + self.workdir = None + # replicate bitbake build environment + self.__exported_vars = None + self.cmd_compile = None + # main build tool used by this recipe + self.build_tool = BuildTool.UNDEFINED + # build_tool = cmake + self.oecmake_generator = None + self.__cmake_cache_vars = None + # build_tool = meson + self.meson_buildtype = None + self.meson_wrapper = None + self.mesonopts = None + self.extra_oemeson = None + self.meson_cross_file = None + # vscode + self.dot_code_dir = None + # TODO: remove calling devtool + self.bb_env_passthrough_additions = None + self.bbpath = None + self.bitbakepath = None + self.topdir = None + + def initialize(self, config, workspace, tinfoil): + recipe_d = parse_recipe( + config, tinfoil, self.name, appends=True, filter_workspace=False) + if not recipe_d: + raise DevtoolError("Parsing %s recipe failed" % self.name) + + # Verify this recipe is built as externalsrc setup by devtool modify + workspacepn = check_workspace_recipe( + workspace, self.name, bbclassextend=True) + self.srctree = workspace[workspacepn]['srctree'] + # Need to grab this here in case the source is within a subdirectory + self.real_srctree = get_real_srctree( + self.srctree, recipe_d.getVar('S'), recipe_d.getVar('WORKDIR')) + self.bbappend = workspace[workspacepn]['bbappend'] + + self.temp_dir = os.path.join(config.workspace_path, 'temp', self.name) + if os.path.exists(self.temp_dir): + shutil.rmtree(self.temp_dir) + + self.b = recipe_d.getVar('B') + self.bpn = recipe_d.getVar('BPN') + self.d = recipe_d.getVar('D') + self.fakerootcmd = recipe_d.getVar('FAKEROOTCMD') + self.fakerootenv = recipe_d.getVar('FAKEROOTENV') + self.package_arch = recipe_d.getVar('PACKAGE_ARCH') + self.path = recipe_d.getVar('PATH') + self.recipe_sysroot = os.path.realpath( + recipe_d.getVar('RECIPE_SYSROOT')) + self.recipe_sysroot_native = os.path.realpath( + recipe_d.getVar('RECIPE_SYSROOT_NATIVE')) + self.staging_incdir = os.path.realpath( + recipe_d.getVar('STAGING_INCDIR')) + self.target_arch = recipe_d.getVar('TARGET_ARCH') + self.workdir = os.path.realpath(recipe_d.getVar('WORKDIR')) + + self.bb_env_passthrough_additions = recipe_d.getVar( + 'BB_ENV_PASSTHROUGH_ADDITIONS') + self.bbpath = recipe_d.getVar('BBPATH') + self.bitbakepath = recipe_d.getVar('BITBAKEPATH') + self.topdir = recipe_d.getVar('TOPDIR') + + self.__init_exported_variables(recipe_d) + + if bb.data.inherits_class('cmake', recipe_d): + self.oecmake_generator = recipe_d.getVar('OECMAKE_GENERATOR') + self.__init_cmake_preset_cache(recipe_d) + self.build_tool = BuildTool.CMAKE + elif bb.data.inherits_class('meson', recipe_d): + self.meson_buildtype = recipe_d.getVar('MESON_BUILDTYPE') + self.mesonopts = recipe_d.getVar('MESONOPTS') + self.extra_oemeson = recipe_d.getVar('EXTRA_OEMESON') + self.meson_cross_file = recipe_d.getVar('MESON_CROSS_FILE') + self.build_tool = BuildTool.MESON + + self.dot_code_dir = os.path.join(self.srctree, '.vscode') + + def append_to_bbappend(self, append_text): + with open(self.bbappend, 'a') as bbap: + bbap.write(append_text) + + def remove_from_bbappend(self, append_text): + with open(self.bbappend, 'r') as bbap: + text = bbap.read() + new_text = text.replace(append_text, '') + with open(self.bbappend, 'w') as bbap: + bbap.write(new_text) + + def debug_build_config(self, args): + """Explicitely set for example CMAKE_BUILD_TYPE to Debug if not defined otherwise""" + if self.build_tool == BuildTool.CMAKE: + append_text = os.linesep + \ + 'OECMAKE_ARGS:append = " -DCMAKE_BUILD_TYPE:STRING=Debug"' + os.linesep + if args.debug_build_config and not 'CMAKE_BUILD_TYPE' in self.__cmake_cache_vars: + self.__cmake_cache_vars['CMAKE_BUILD_TYPE'] = { + "type": "STRING", + "value": "Debug", + } + self.append_to_bbappend(append_text) + elif 'CMAKE_BUILD_TYPE' in self.__cmake_cache_vars: + del self.__cmake_cache_vars['CMAKE_BUILD_TYPE'] + self.remove_from_bbappend(append_text) + elif self.build_tool == BuildTool.MESON: + append_text = os.linesep + 'MESON_BUILDTYPE = "debug"' + os.linesep + if args.debug_build_config and self.meson_buildtype != "debug": + self.mesonopts.replace( + '--buildtype ' + self.meson_buildtype, '--buildtype debug') + self.append_to_bbappend(append_text) + elif self.meson_buildtype == "debug": + self.mesonopts.replace( + '--buildtype debug', '--buildtype plain') + self.remove_from_bbappend(append_text) + elif args.debug_build_config: + logger.warn( + "--debug-build-config is not implemented for this build tool yet.") + + def solib_search_path_sysroot(self): + return [os.path.join(self.recipe_sysroot, p) for p in ['lib', 'usr/lib']] + + def solib_search_path(self, image): + return image.solib_search_path_rootfs() + self.solib_search_path_sysroot() + + def solib_search_path_str(self, image): + return ':'.join(self.solib_search_path(image)) + + def __init_exported_variables(self, d): + """Find all variables with export flag set.""" + exported_vars = {} + + vars = (key for key in d.keys() if not key.startswith( + "__") and not d.getVarFlag(key, "func", False)) + for var in vars: + func = d.getVarFlag(var, "func", False) + if d.getVarFlag(var, 'python', False) and func: + continue + export = d.getVarFlag(var, "export", False) + unexport = d.getVarFlag(var, "unexport", False) + if not export and not unexport and not func: + continue + if unexport: + continue + + val = d.getVar(var) + if val is None: + continue + if set(var) & set("-.{}+"): + logger.warn( + "Warning: Found invalid character in variable name %s", str(var)) + continue + varExpanded = d.expand(var) + val = str(val) + + if varExpanded.startswith("BASH_FUNC_"): + varExpanded = varExpanded[10:-2] + val = val[3:] # Strip off "() " + logger.warn("Warning: BASH_FUNC_ is not exported to cmake presets (%s() %s)" % ( + varExpanded, val)) + continue + + if func: + code_line = "line: {0}, file: {1}\n".format( + d.getVarFlag(var, "lineno", False), + d.getVarFlag(var, "filename", False)) + val = val.rstrip('\n') + logger.warn("Warning: exported shell function %s() is not exported (%s)" % + (varExpanded, code_line)) + continue + + if export: + exported_vars[varExpanded] = val.strip() + continue + + self.__exported_vars = exported_vars + + def __init_cmake_preset_cache(self, d): + """Replicate the cmake configure arguments with all details to share on build folder between bitbake and SDK.""" + site_file = os.path.join(self.workdir, 'site-file.cmake') + if os.path.exists(site_file): + print("Warning: site-file.cmake is not supported") + + cache_vars = {} + oecmake_args = d.getVar('OECMAKE_ARGS').split() + extra_oecmake = d.getVar('EXTRA_OECMAKE').split() + for param in oecmake_args + extra_oecmake: + d_pref = "-D" + if param.startswith(d_pref): + param = param[len(d_pref):] + else: + print("Error: expected a -D") + param_s = param.split('=', 1) + param_nt = param_s[0].split(':', 1) + + def handle_undefined_variable(var): + if var.startswith('${') and var.endswith('}'): + return '' + else: + return var + # Example: FOO=ON + if len(param_nt) == 1: + cache_vars[param_s[0]] = handle_undefined_variable(param_s[1]) + # Example: FOO:PATH=/tmp + elif len(param_nt) == 2: + cache_vars[param_nt[0]] = { + "type": param_nt[1], + "value": handle_undefined_variable(param_s[1]), + } + else: + print("Error: cannot parse %s" % param) + self.__cmake_cache_vars = cache_vars + + def __cmake_preset(self): + toolchain_file = os.path.join(self.workdir, 'toolchain.cmake') + preset_name = self.bpn + "-" + self.package_arch + preset_display_name = self.bpn + ": " + self.package_arch + cmake_executable = os.path.join( + self.recipe_sysroot_native, 'usr', 'bin', 'cmake') + self.cmd_compile = cmake_executable + " --build --preset " + preset_name + + preset_dict_configure = { + "name": preset_name, + "displayName": preset_display_name, + "description": "Bitbake build environment for the recipe %s compiled for %s" % (self.bpn, self.package_arch), + "binaryDir": self.b, + "generator": self.oecmake_generator, + "toolchainFile": toolchain_file, + "cacheVariables": self.__cmake_cache_vars, + "environment": self.__exported_vars, + "cmakeExecutable": cmake_executable + } + + preset_dict_build = { + "name": preset_name, + "displayName": preset_display_name, + "description": "Bitbake build environment for the recipe %s compiled for %s" % (self.bpn, self.package_arch), + "configurePreset": preset_name, + "inheritConfigureEnvironment": True + } + + preset_dict_test = { + "name": preset_name, + "displayName": preset_display_name, + "description": "Bitbake build environment for the recipe %s compiled for %s" % (self.bpn, self.package_arch), + "configurePreset": preset_name, + "inheritConfigureEnvironment": True + } + + preset_dict = { + "version": 3, # cmake 3.21, backward compatible with kirkstone + "configurePresets": [preset_dict_configure], + "buildPresets": [preset_dict_build], + "testPresets": [preset_dict_test] + } + + logger.info("generating cmake preset for recipe %s" % self.bpn) + preset_file = os.path.join(self.real_srctree, 'CMakeUserPresets.json') + with open(preset_file, 'w') as outfile: + json.dump(preset_dict, outfile, indent=4) + + @staticmethod + def update_json_file(dot_code_dir, json_file, update_dict): + json_path = os.path.join(dot_code_dir, json_file) + logger.info("Updating vscode %s (%s)" % (json_file, json_path)) + if not os.path.exists(dot_code_dir): + os.makedirs(dot_code_dir) + try: + with open(json_path) as f: + orig_dict = json.load(f) + except json.decoder.JSONDecodeError: + logger.info( + "Decoding %s failed. Probably because of comments in the json file" % json_path) + orig_dict = {} + except FileNotFoundError: + orig_dict = {} + orig_dict.update(update_dict) + with open(json_path, 'w') as f: + json.dump(orig_dict, f, indent=4) + + def __vscode_settings_cmake(self, settings_dict): + """Add cmake specific settings to settings.json. + + Note: most settings are passed to the cmake preset. + """ + if self.build_tool != BuildTool.CMAKE: + return + settings_dict["cmake.configureOnOpen"] = False + settings_dict["cmake.sourceDirectory"] = self.real_srctree + + def __gen_meson_wrapper(self): + """Generate a wrapper script to call meson with cross environment""" + bb.utils.mkdirhier(self.temp_dir) + meson_wrapper = os.path.join(self.temp_dir, 'meson') + meson_real = os.path.join( + self.recipe_sysroot_native, 'usr', 'bin', 'meson.real') + with open(meson_wrapper, 'w') as mwrap: + mwrap.write("#!/bin/sh" + os.linesep) + for var, val in self.__exported_vars.items(): + mwrap.write('export %s="%s"' % (var, val) + os.linesep) + mwrap.write("unset CC CXX CPP LD AR NM STRIP" + os.linesep) + private_temp = os.path.join(self.b, "meson-private", "tmp") + mwrap.write('mkdir -p "%s"' % private_temp + os.linesep) + mwrap.write('export TMPDIR="%s"' % private_temp + os.linesep) + mwrap.write('exec "%s" "$@"' % meson_real + os.linesep) + st = os.stat(meson_wrapper) + os.chmod(meson_wrapper, st.st_mode | stat.S_IEXEC) + self.meson_wrapper = meson_wrapper + self.cmd_compile = meson_wrapper + " compile -C " + self.b + + def __vscode_settings_meson(self, settings_dict): + if self.build_tool != BuildTool.MESON: + return + settings_dict["mesonbuild.mesonPath"] = self.meson_wrapper + + confopts = self.mesonopts.split() + confopts += self.meson_cross_file.split() + confopts += self.extra_oemeson.split() + settings_dict["mesonbuild.configureOptions"] = confopts + settings_dict["mesonbuild.buildFolder"] = self.b + + def vscode_settings(self): + files_excludes = { + "**/.git/**": True, + "**/oe-local-files/**": True, + "**/oe-logs/**": True, + "**/oe-workdir/**": True, + "**/source-date-epoch/**": True + } + python_exclude = [ + "**/.git/**", + "**/oe-local-files/**", + "**/oe-logs/**", + "**/oe-workdir/**", + "**/source-date-epoch/**" + ] + settings_dict = { + "files.watcherExclude": files_excludes, + "files.exclude": files_excludes, + "python.analysis.exclude": python_exclude + } + self.__vscode_settings_cmake(settings_dict) + self.__vscode_settings_meson(settings_dict) + + settings_file = 'settings.json' + RecipeModified.update_json_file( + self.dot_code_dir, settings_file, settings_dict) + + def __vscode_extensions_cmake(self, recommendations): + if self.build_tool != BuildTool.CMAKE: + return + recommendations += [ + "twxs.cmake", + "ms-vscode.cmake-tools", + "ms-vscode.cpptools", + "ms-vscode.cpptools-extension-pack", + "ms-vscode.cpptools-themes" + ] + + def __vscode_extensions_meson(self, recommendations): + if self.build_tool != BuildTool.MESON: + return + recommendations += [ + 'mesonbuild.mesonbuild' + ] + + def vscode_extensions(self): + recommendations = [ + "EditorConfig.EditorConfig" + ] + self.__vscode_extensions_cmake(recommendations) + self.__vscode_extensions_meson(recommendations) + extensions_file = 'extensions.json' + RecipeModified.update_json_file( + self.dot_code_dir, extensions_file, {"recommendations": recommendations}) + + def which(self, executable): + bin_path = shutil.which(executable, path=self.path) + if not bin_path: + raise DevtoolError( + 'Cannot find %s. Probably the recipe %s is not built yet.' % (executable, self.bpn)) + return bin_path + + @staticmethod + def vscode_intelli_sense_mode(compiler): + unknown = False + linux = '' + if 'linux' in compiler: + linux = "linux-" + + cxx = 'unknown-' + if 'g++' in compiler: + cxx = 'gcc-' + elif 'clang' in compiler: + cxx = 'clang-' + else: + unknown = True + + arch = 'unknown' + if 'aarch64' in compiler: + arch = 'arm64' + elif 'arm' in compiler: + arch = 'arm' + elif 'x86_64' in compiler: + arch = 'x64' + elif 'i386' in compiler: + arch = 'x86' + else: + unknown = True + + mode = linux + cxx + arch + if unknown: + logger.warn( + "Cannot guess intelliSenseMode for compiler %s (%s)" % (compiler, mode)) + return '${default}' + return mode + + def vscode_c_cpp_properties(self): + properties_dict = { + "name": "Yocto " + self.package_arch, + } + if self.build_tool == BuildTool.CMAKE: + properties_dict["configurationProvider"] = "ms-vscode.cmake-tools" + elif self.build_tool == BuildTool.MESON: + properties_dict["configurationProvider"] = "mesonbuild.mesonbuild" + + properties_dicts = { + "configurations": [ + properties_dict + ], + "version": 4 + } + prop_file = 'c_cpp_properties.json' + dot_code_dir = os.path.join(self.srctree, '.vscode') + RecipeModified.update_json_file( + dot_code_dir, prop_file, properties_dicts) + + def vscode_launch_cppdbg(self, image, gdb_cross, binary): + gdb_cross.setup_gdbserver_config(binary, self.temp_dir) + pretty_id = gdb_cross.get_gdbserver_pretty_id(binary) + gdbserver_port = gdb_cross.get_gdbserver_port(binary) + + launch_config = { + "name": pretty_id, + "type": "cppdbg", + "request": "launch", + "program": os.path.join(self.d, binary.lstrip('/')), + "stopAtEntry": True, + "cwd": "${workspaceFolder}", + "environment": [], + "externalConsole": False, + "MIMode": "gdb", + "preLaunchTask": pretty_id, + "miDebuggerPath": gdb_cross.gdb, + "miDebuggerServerAddress": "%s:%d" % (gdb_cross.host, gdbserver_port) + } + + # Search for header files in recipe-sysroot. + src_file_map = { + "/usr/include": os.path.join(self.recipe_sysroot, "usr", "include") + } + # First of all search for not stripped binaries in the image folder. + # These binaries are copied (and optionally stripped) by deploy-target + setup_commands = [ + { + "description": "sysroot", + "text": "set sysroot " + self.d + } + ] + + if image.rootfs_dbg: + launch_config['additionalSOLibSearchPath'] = self.solib_search_path_str( + image) + src_file_map["/usr/src/debug"] = os.path.join( + image.rootfs_dbg, "usr", "src", "debug") + else: + logger.warning( + "Cannot setup debug symbols configuration for GDB. IMAGE_GEN_DEBUGFS is not enabled.") + + launch_config['sourceFileMap'] = src_file_map + launch_config['setupCommands'] = setup_commands + return launch_config + + @staticmethod + def is_elf_file(file_path): + with open(file_path, "rb") as f: + data = f.read(4) + if data == b'\x7fELF': + return True + return False + + def find_installed_binaries(self): + """find all executable elf files in the image directory""" + binaries = [] + d_len = len(self.d) + re_so = re.compile('.*\.so[.0-9]*$') + for root, _, files in os.walk(self.d, followlinks=False): + for file in files: + if os.path.islink(file): + continue + if re_so.match(file): + continue + abs_name = os.path.join(root, file) + if os.access(abs_name, os.X_OK) and RecipeModified.is_elf_file(abs_name): + binaries.append(abs_name[d_len:]) + return binaries + + def vscode_launch(self, image, gdb_cross): + binaries = self.find_installed_binaries() + configurations = [self.vscode_launch_cppdbg( + image, gdb_cross, binary) for binary in binaries] + launch_dict = { + "version": "0.2.0", + "configurations": configurations + } + launch_file = 'launch.json' + RecipeModified.update_json_file( + self.dot_code_dir, launch_file, launch_dict) + + @staticmethod + def get_unique_gdbinit_name(binary): + return 'gdbinit' + binary.replace(os.sep, '-') + + def none_launch(self, image, gdb_cross): + """generate a gdbinit file per executable""" + binaries = self.find_installed_binaries() + for binary in binaries: + gdb_cross.setup_gdbserver_config(binary, self.temp_dir) + gdbserver_port = str(gdb_cross.get_gdbserver_port(binary)) + if gdb_cross.gdbserver_multi: + target_help = '# gdbserver --multi :' + gdbserver_port + remote_cmd = 'target extended-remote ' + else: + target_help = '# gdbserver :' + gdbserver_port + ' ' + binary + remote_cmd = 'target remote ' + gdbinit_path = os.path.join( + self.real_srctree, RecipeModified.get_unique_gdbinit_name(binary)) + + gdbinit_lines = ['# This file is generated by devtool ide'] + gdbinit_lines.append('# On the remote target:') + gdbinit_lines.append(target_help) + gdbinit_lines.append('# On the build machine:') + gdbinit_lines.append('# cd ' + self.real_srctree) + gdbinit_lines.append( + '# ' + gdb_cross.gdb + ' -ix ' + gdbinit_path) + + gdbinit_lines.append('set sysroot ' + self.d) + gdbinit_lines.append('set substitute-path "/usr/include" "' + + os.path.join(self.recipe_sysroot, 'usr', 'include') + '"') + if image.debuginfod: + gdbinit_lines.append('set debuginfod enabled on') + else: + gdbinit_lines.append('set debuginfod enabled off') + if image.rootfs_dbg: + gdbinit_lines.append( + 'set solib-search-path "' + self.solib_search_path_str(image) + '"') + gdbinit_lines.append('set substitute-path "/usr/src/debug" "' + os.path.join( + image.rootfs_dbg, 'usr', 'src', 'debug') + '"') + gdbinit_lines.append( + remote_cmd + gdb_cross.host + ':' + gdbserver_port) + gdbinit_lines.append('set remote exec-file ' + binary) + gdbinit_lines.append('run ' + os.path.join(self.d, binary)) + + with open(gdbinit_path, 'w') as gdbinit_file: + gdbinit_file.write('\n'.join(gdbinit_lines)) + + def gen_fakeroot_install_script(self): + """Run the run.do_install script from bitbake under pseudo so that it picks up the appropriate file permissions""" + cmd_lines = ['#!/bin/sh'] + # Ensure the do compile step gets always executed without pseuso before do install + if self.cmd_compile: + cmd_compile = "( cd %s && %s)" % ( + self.real_srctree, self.cmd_compile) + cmd_lines.append(cmd_compile) + if not os.access(self.fakerootcmd, os.X_OK): + raise DevtoolError( + "pseudo executable %s could not be found" % self.fakerootcmd) + run_do_install = os.path.join(self.workdir, 'temp', 'run.do_install') + + if not os.access(run_do_install, os.X_OK): + raise DevtoolError( + "run script does not exists: %s" % run_do_install) + + # Set up the appropriate environment + newenv = dict(os.environ) + for varvalue in self.fakerootenv.split(): + if '=' in varvalue: + splitval = varvalue.split('=', 1) + newenv[splitval[0]] = splitval[1] + + # Cleanup TMPDIR before calling do_install independently from bitbake + # This is anyway outdated after do_install has been executed. + # But maybe there should be a cleaner solution here. + rm_in_workdir = ' '.join([os.path.join(self.workdir, d) for d in [ + "package", "packages-split", "pkgdata", "sstate-install-package", "debugsources.list", "*.spec"]]) + install_cmd = '%s /bin/sh -c "rm -rf %s/* %s && %s"' % ( + self.fakerootcmd, self.d, rm_in_workdir, run_do_install) + for var, val in newenv.items(): + cmd_lines.append('export %s="%s"' % (var, val)) + cmd_lines.append(install_cmd) + return self.write_script(cmd_lines, 'bb_run_do_install') + + def write_script(self, cmd_lines, script_name): + bb.utils.mkdirhier(self.temp_dir) + script_file = os.path.join(self.temp_dir, script_name) + with open(script_file, 'w') as script_f: + script_f.write(os.linesep.join(cmd_lines)) + st = os.stat(script_file) + os.chmod(script_file, st.st_mode | stat.S_IEXEC) + return script_file + + def vscode_tasks(self, args, gdb_cross): + run_do_install = self.gen_fakeroot_install_script() + pythonpath_new = os.path.realpath( + os.path.join(self.bitbakepath, '../lib')) + try: + pythonpath = os.environ['PYTONPATH'].split(':') + if pythonpath_new not in pythonpath: + pythonpath = pythonpath_new + ":" + pythonpath + except KeyError: + pythonpath = pythonpath_new + install_label = "do_install %s" % self.bpn + deploy_label = "devtool deploy-target %s" % self.bpn + bb_env = { + # "BBPATH": self.bbpath, + "PYTHONPATH": pythonpath, + "BUILDDIR": self.topdir, + # Use e.g. Python from host, not python-native + "PATH": os.environ['PATH'], + "BB_ENV_PASSTHROUGH_ADDITIONS": self.bb_env_passthrough_additions + } + bb_options = { + "cwd": self.topdir + } + tasks_dict = { + "version": "2.0.0", + "tasks": [ + { + "label": install_label, + "type": "shell", + "command": run_do_install, + "problemMatcher": [] + }, + { + "label": deploy_label, + "type": "shell", + "command": "devtool", # TODO: Generate a self contained script which does what devtool target-deploy does but without connection to the bitbake server + "args": ["--bbpath", self.bbpath, "deploy-target", self.bpn, args.target, "--strip", "--no-host-check"], + "linux": { + "options": { + "env": bb_env + }}, + "options": bb_options, + "problemMatcher": [] + }, + { + "label": "install && deploy-target %s" % self.bpn, + "dependsOrder": "sequence", + "dependsOn": [ + install_label, + deploy_label + ], + "problemMatcher": [], + "group": { + "kind": "build", + "isDefault": True + } + } + ] + } + for pretty_id, start_script in gdb_cross.get_gdbserver_start_scripts(): + tasks_dict['tasks'].append( + { + "label": pretty_id, + "type": "shell", + "isBackground": True, + "command": start_script, + "problemMatcher": [ + { + "pattern": [ + { + "regexp": ".", + "file": 1, + "location": 2, + "message": 3 + } + ], + "background": { + "activeOnStart": True, + "beginsPattern": ".", + "endsPattern": ".", + } + } + ] + }) + tasks_file = 'tasks.json' + RecipeModified.update_json_file( + self.dot_code_dir, tasks_file, tasks_dict) + + def setup_ide(self, args, image, gdb_cross): + if self.build_tool == BuildTool.CMAKE: + self.__cmake_preset() + if self.build_tool == BuildTool.MESON: + self.__gen_meson_wrapper() + + if args.ide == 'code': + self.vscode_settings() + self.vscode_extensions() + self.vscode_c_cpp_properties() + if args.target: + self.vscode_launch(image, gdb_cross) + self.vscode_tasks(args, gdb_cross) + if args.ide == 'none' and self.build_tool == BuildTool.CMAKE: + self.none_launch(image, gdb_cross) + + +def ide_setup(args, config, basepath, workspace): + bootstap_tasks = [] + + tinfoil = setup_tinfoil(config_only=False, basepath=basepath) + try: + # Provide a rootfs and the corresponding debug symbols via rootfs-dbg or debuginfod + image_config = RecipeImage(args.image) + image_config.initialize(config, tinfoil) + bootstap_tasks += image_config.bootstrap_tasks + + target_device = TargetDevice(args) + + sdk_env = None + gdb_cross = None + if args.recipename in SHARED_SYSROOT_RECIPES: + ide_support = RecipeMetaIdeSupport() + ide_support.initialize(config, tinfoil) + bootstap_tasks += ide_support.bootstrap_tasks + + build_sysroots = RecipeBuildSysroots() + build_sysroots.initialize(config, tinfoil) + bootstap_tasks += build_sysroots.bootstrap_tasks + + sdk_env = SharedSysrootsEnv() + sdk_env.initialize(ide_support, build_sysroots) + else: + sdk_env = RecipeModified(args.recipename) + sdk_env.initialize(config, workspace, tinfoil) + bootstap_tasks += sdk_env.bootstrap_tasks + + gdb_multi_mode = not bool(args.ide == 'code') + gdb_cross = RecipeGdbCross( + args, sdk_env.target_arch, target_device, gdb_multi_mode) + gdb_cross.initialize(config, workspace, tinfoil) + bootstap_tasks += gdb_cross.bootstrap_tasks + finally: + tinfoil.shutdown() + + shared_sysroot = bool(args.recipename in SHARED_SYSROOT_RECIPES) + if not shared_sysroot: + sdk_env.debug_build_config(args) + + if not args.skip_bitbake: + bb_cmd = 'bitbake ' + if args.bitbake_k: + bb_cmd += "-k " + bb_cmd += ' '.join(bootstap_tasks) + exec_build_env_command(config.init_path, basepath, bb_cmd, watch=True) + + if shared_sysroot: + sdk_env.setup_ide(args) + else: + sdk_env.setup_ide(args, image_config, gdb_cross) + + +def get_default_ide(): + for an_ide in SUPPORTED_IDES[:-1]: + if shutil.which(an_ide): + return an_ide + return SUPPORTED_IDES[-1:] + + +def register_commands(subparsers, context): + """Register devtool subcommands from this plugin""" + parser_ide = subparsers.add_parser('ide', help='Setup the IDE (VSCode)', + description='Configure the IDE to work with the source code of a recipe.', + group='working', order=50, formatter_class=RawTextHelpFormatter) + parser_ide.add_argument( + 'recipename', help='Generate a IDE configuration in the workspace of the given recipe. ' + 'By default the workspace is configured to use the recipe sysroot prepared by devtool modify. ' + 'For some special recipes the generated configuration referes to the shared sysroots ' + 'provided by meta-ide-setup and build-sysroots recipes. ' + 'The following recipes use a shared sysroot: %s' % SHARED_SYSROOT_RECIPES) + parser_ide.add_argument( + 'image', help='The image running on the target device. This is required for remote debugging.' + 'It is important to deploy the image built by this command to the target device because ' + 'otherwise the debug symbols used on the build machine (rootfs-dbg) are probably out of sync ' + 'with the binaries executed on the target device.') + parser_ide.add_argument( + '-i', '--ide', choices=SUPPORTED_IDES, default=get_default_ide(), + help='Setup the configuration for this IDE') + parser_ide.add_argument( + '-t', '--target', default='root@192.168.7.2', + help='Live target machine running an ssh server: user@hostname.') + parser_ide.add_argument( + '-G', '--gdbserver-port-start', default="1234", help='port where gdbserver is listening.') + parser_ide.add_argument( + '-c', '--no-host-check', help='Disable ssh host key checking', action='store_true') + parser_ide.add_argument( + '-e', '--ssh-exec', help='Executable to use in place of ssh') + parser_ide.add_argument( + '-P', '--port', help='Specify ssh port to use for connection to the target') + parser_ide.add_argument( + '-I', '--key', help='Specify ssh private key for connection to the target') + parser_ide.add_argument( + '--skip-bitbake', help='Generate IDE configuration but skip calling bibtake to update the SDK.', action='store_true') + parser_ide.add_argument( + '-k', '--bitbake-k', help='Pass -k parameter to bitbake', action='store_true') + parser_ide.add_argument( + '--debug-build-config', help='Use debug build flags, for example set CMAKE_BUILD_TYPE=Debug', action='store_true') + parser_ide.set_defaults(func=ide_setup) + + # TODO: Better support for multiple recipes. E.g. a list of recipes with auto-detection for the image recipe or all modified recipes From patchwork Sun Sep 10 15:52:30 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adrian Freihofer X-Patchwork-Id: 30255 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 AD03BEEB58C for ; Sun, 10 Sep 2023 16:19:29 +0000 (UTC) Received: from mail-wm1-f48.google.com (mail-wm1-f48.google.com [209.85.128.48]) by mx.groups.io with SMTP id smtpd.web10.39053.1694362763999895915 for ; Sun, 10 Sep 2023 09:19:24 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20221208 header.b=kwFxRbp3; spf=pass (domain: gmail.com, ip: 209.85.128.48, mailfrom: adrian.freihofer@gmail.com) Received: by mail-wm1-f48.google.com with SMTP id 5b1f17b1804b1-401d10e3e54so39924635e9.2 for ; Sun, 10 Sep 2023 09:19:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1694362762; x=1694967562; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=VaWuuIUtmaan9OQ7nZXD7CNTUSo25dmTfn2Y4hW5+Sg=; b=kwFxRbp3u6IVDr+VmGs/NjByHwWJScoHhNrPurT/070UlrAVdlmbDxA8ktBhd4vqYJ mTkgNaojXTxsrJUgfbTYaxw3BmYKbechQ9D7bJMuoLf/0SF8O1cfIO8TGOULg5h01rvn BbL4HjavmztHyebae15NAUoi5F6YbFZ+fVG2mCF+DVWlYjNtvpKmWySyVBDa5kXcG41Y /sO30rxTPvajW5EWuYMiDWNwl9RSg6aI2yXHLwf01il4fbq1socVs1CGIMGumTXOYtPH 1K8r8qgExp66I9+veWBKavhk3EpNkmEVNEt5xwnyaV/crK/7Y6/LQJvwS3jNoVIp/ufI 1eyA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1694362762; x=1694967562; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=VaWuuIUtmaan9OQ7nZXD7CNTUSo25dmTfn2Y4hW5+Sg=; b=mURuixrIck+lU6MKcYRpsvL5oh9BHWw+7g3fe7OdVTHAfc6UsZY/k3YazRRWBhn4pz sM6dk5LzqowYabxmM5eY1wr8o54sa44Nh5KZIHoMi0bvkZ9pietjCjmyoXB3Z901qLDE achPkUlhu5vkyUWKp7WbAsthj0xADbjMHL2fHUt/z7jwF9e91HJK9MG7/2IFdsWu6CiZ R0GmI8b05MWTt3jJ6LJmEyjojfXfdlm+KV9mV5GBkd5La+NtkncfviAQgU/wQ+PWJzRs YNEqAR28eCN4gWiVisqjn0pPuTKpR+HtkD49OlJUX6Yn22QARYgig4RtOPh/UevVWRi4 ZmLA== X-Gm-Message-State: AOJu0YxVE3KHIljLhHHuD9140/HuajQmqPtpkU9GJzLSX2GOnsEZi5K8 wwyk1lKy025Ic+TkWnQjkRFvbhaQnU0= X-Google-Smtp-Source: AGHT+IHo+AzXDyHD+VdStSwHOID76bDF/XBfanojsDF8wDba16j/3RHxAWpVcHuxPcSPpfEEdTzW+Q== X-Received: by 2002:a05:600c:2a50:b0:402:bda9:74d1 with SMTP id x16-20020a05600c2a5000b00402bda974d1mr6218297wme.8.1694362762194; Sun, 10 Sep 2023 09:19:22 -0700 (PDT) Received: from t14s-af.fritz.box ([2a02:169:59a6:0:dcf2:2f65:9442:83f]) by smtp.gmail.com with ESMTPSA id o12-20020a5d408c000000b003142ea7a661sm7605431wrp.21.2023.09.10.09.19.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 Sep 2023 09:19:21 -0700 (PDT) From: Adrian Freihofer X-Google-Original-From: Adrian Freihofer To: openembedded-core@lists.openembedded.org Cc: Adrian Freihofer Subject: [OE-core][PATCH v6 04/12] tests: add a C++ example recipe Date: Sun, 10 Sep 2023 17:52:30 +0200 Message-ID: <20230910161850.4032227-5-adrian.freihofer@siemens.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230910161850.4032227-1-adrian.freihofer@siemens.com> References: <20230910161850.4032227-1-adrian.freihofer@siemens.com> MIME-Version: 1.0 List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Sun, 10 Sep 2023 16:19:29 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/187462 This simple C++ project supports compilation with cmake and with meson. It's supposed to be used with oe-selftest for the devtool ide plugin. Signed-off-by: Adrian Freihofer --- meta-selftest/recipes-test/cpp/.gitignore | 1 + .../recipes-test/cpp/cmake-example.bb | 17 ++++++ .../recipes-test/cpp/cmake-example/run-ptest | 10 ++++ .../recipes-test/cpp/cpp-example.inc | 24 ++++++++ .../recipes-test/cpp/files/CMakeLists.txt | 60 +++++++++++++++++++ .../cpp/files/cpp-example-lib.cpp | 17 ++++++ .../cpp/files/cpp-example-lib.hpp | 16 +++++ .../recipes-test/cpp/files/cpp-example.cpp | 16 +++++ .../recipes-test/cpp/files/meson.build | 34 +++++++++++ .../cpp/files/test-cpp-example.cpp | 19 ++++++ .../recipes-test/cpp/meson-example.bb | 17 ++++++ .../recipes-test/cpp/meson-example/run-ptest | 10 ++++ 12 files changed, 241 insertions(+) create mode 100644 meta-selftest/recipes-test/cpp/.gitignore create mode 100644 meta-selftest/recipes-test/cpp/cmake-example.bb create mode 100644 meta-selftest/recipes-test/cpp/cmake-example/run-ptest create mode 100644 meta-selftest/recipes-test/cpp/cpp-example.inc create mode 100644 meta-selftest/recipes-test/cpp/files/CMakeLists.txt create mode 100644 meta-selftest/recipes-test/cpp/files/cpp-example-lib.cpp create mode 100644 meta-selftest/recipes-test/cpp/files/cpp-example-lib.hpp create mode 100644 meta-selftest/recipes-test/cpp/files/cpp-example.cpp create mode 100644 meta-selftest/recipes-test/cpp/files/meson.build create mode 100644 meta-selftest/recipes-test/cpp/files/test-cpp-example.cpp create mode 100644 meta-selftest/recipes-test/cpp/meson-example.bb create mode 100644 meta-selftest/recipes-test/cpp/meson-example/run-ptest diff --git a/meta-selftest/recipes-test/cpp/.gitignore b/meta-selftest/recipes-test/cpp/.gitignore new file mode 100644 index 00000000000..30d388a12b7 --- /dev/null +++ b/meta-selftest/recipes-test/cpp/.gitignore @@ -0,0 +1 @@ +build* \ No newline at end of file diff --git a/meta-selftest/recipes-test/cpp/cmake-example.bb b/meta-selftest/recipes-test/cpp/cmake-example.bb new file mode 100644 index 00000000000..96d543180b4 --- /dev/null +++ b/meta-selftest/recipes-test/cpp/cmake-example.bb @@ -0,0 +1,17 @@ +# +# Copyright OpenEmbedded Contributors +# +# SPDX-License-Identifier: MIT +# + +SUMMARY = "A C++ example compiled with cmake." + +inherit cmake + +require cpp-example.inc + +SRC_URI += "\ + file://CMakeLists.txt \ +" + +FILES:${PN}-ptest += "${bindir}/test-cmake-example" diff --git a/meta-selftest/recipes-test/cpp/cmake-example/run-ptest b/meta-selftest/recipes-test/cpp/cmake-example/run-ptest new file mode 100644 index 00000000000..94b620a1984 --- /dev/null +++ b/meta-selftest/recipes-test/cpp/cmake-example/run-ptest @@ -0,0 +1,10 @@ +#!/bin/sh +# +# Copyright OpenEmbedded Contributors +# +# SPDX-License-Identifier: MIT +# + +test-cmake-example + +# Note: run-ptests exits with exit value from test-cmake-example diff --git a/meta-selftest/recipes-test/cpp/cpp-example.inc b/meta-selftest/recipes-test/cpp/cpp-example.inc new file mode 100644 index 00000000000..39c61cf4ceb --- /dev/null +++ b/meta-selftest/recipes-test/cpp/cpp-example.inc @@ -0,0 +1,24 @@ +# +# Copyright OpenEmbedded Contributors +# +# SPDX-License-Identifier: MIT +# + +LICENSE = "MIT" +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302" + +inherit ptest + +DEPENDS += "json-c" + +PV = "1.0" + +S = "${WORKDIR}" + +SRC_URI = "\ + file://cpp-example.cpp \ + file://cpp-example-lib.hpp \ + file://cpp-example-lib.cpp \ + file://test-cpp-example.cpp \ + file://run-ptest \ +" diff --git a/meta-selftest/recipes-test/cpp/files/CMakeLists.txt b/meta-selftest/recipes-test/cpp/files/CMakeLists.txt new file mode 100644 index 00000000000..839aa59b5e3 --- /dev/null +++ b/meta-selftest/recipes-test/cpp/files/CMakeLists.txt @@ -0,0 +1,60 @@ +# +# Copyright OpenEmbedded Contributors +# +# SPDX-License-Identifier: MIT +# + +cmake_minimum_required(VERSION 3.22) + +project(cmake-example + VERSION 1.0.0 + LANGUAGES CXX +) + +option(BUILD_SHARED_LIBS "Build using shared libraries" ON) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED On) +set(CMAKE_CXX_EXTENSIONS Off) + +include(GNUInstallDirs) + +# Find json-c +# find_package(PkgConfig REQUIRED) +# pkg_check_modules(JSONC REQUIRED json-c) +find_package(json-c) + +# A simple library linking json-c library found by pkgconfig +add_library(cmake-example-lib cpp-example-lib.cpp cpp-example-lib.hpp) +set_target_properties(cmake-example-lib PROPERTIES + VERSION ${PROJECT_VERSION} + SOVERSION ${PROJECT_VERSION_MAJOR} +) +target_link_libraries(cmake-example-lib PRIVATE json-c::json-c) +# target_link_libraries(cmake-example-lib ${JSONC_LIBRARIES}) +# target_include_directories(cmake-example-lib PUBLIC ${JSONC_INCLUDE_DIRS}) +# target_compile_options(cmake-example-lib PUBLIC ${JSONC_CFLAGS_OTHER}) +install(TARGETS cmake-example-lib + INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} +) + +# A simple executable linking the library +add_executable(cmake-example cpp-example.cpp) +target_link_libraries(cmake-example PRIVATE cmake-example-lib) + +install(TARGETS cmake-example + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} +) + +# A simple test executable for testing the library +add_executable(test-cmake-example test-cpp-example.cpp) +target_link_libraries(test-cmake-example PRIVATE cmake-example-lib) + +install(TARGETS test-cmake-example + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} +) + +include(CTest) +add_test(NAME test-cmake-example COMMAND test-cmake-example) diff --git a/meta-selftest/recipes-test/cpp/files/cpp-example-lib.cpp b/meta-selftest/recipes-test/cpp/files/cpp-example-lib.cpp new file mode 100644 index 00000000000..29fd10fb7e1 --- /dev/null +++ b/meta-selftest/recipes-test/cpp/files/cpp-example-lib.cpp @@ -0,0 +1,17 @@ +/* +* Copyright OpenEmbedded Contributors +* +* SPDX-License-Identifier: MIT +*/ + +#include +#include +#include "cpp-example-lib.hpp" + +const std::string& CppExample::get_string() { + return test_string; +} + +const char* CppExample::get_json_c_version() { + return json_c_version(); +} diff --git a/meta-selftest/recipes-test/cpp/files/cpp-example-lib.hpp b/meta-selftest/recipes-test/cpp/files/cpp-example-lib.hpp new file mode 100644 index 00000000000..8a87e6b510a --- /dev/null +++ b/meta-selftest/recipes-test/cpp/files/cpp-example-lib.hpp @@ -0,0 +1,16 @@ +/* +* Copyright OpenEmbedded Contributors +* +* SPDX-License-Identifier: MIT +*/ + +#pragma once + +#include + +struct CppExample { + inline static const std::string test_string = "cpp-example-lib Magic: 123456789"; + + const std::string& get_string(); + const char* get_json_c_version(); +}; diff --git a/meta-selftest/recipes-test/cpp/files/cpp-example.cpp b/meta-selftest/recipes-test/cpp/files/cpp-example.cpp new file mode 100644 index 00000000000..de7f2106dec --- /dev/null +++ b/meta-selftest/recipes-test/cpp/files/cpp-example.cpp @@ -0,0 +1,16 @@ +/* +* Copyright OpenEmbedded Contributors +* +* SPDX-License-Identifier: MIT +*/ + +#include "cpp-example-lib.hpp" + +#include + +int main() { + auto cpp_example = CppExample(); + std::cout << "C++ example linking " << cpp_example.get_string() << std::endl; + std::cout << "Linking json-c version " << cpp_example.get_json_c_version() << std::endl; + return 0; +} diff --git a/meta-selftest/recipes-test/cpp/files/meson.build b/meta-selftest/recipes-test/cpp/files/meson.build new file mode 100644 index 00000000000..7753da69721 --- /dev/null +++ b/meta-selftest/recipes-test/cpp/files/meson.build @@ -0,0 +1,34 @@ +# +# Copyright OpenEmbedded Contributors +# +# SPDX-License-Identifier: MIT +# + +project('meson-example', 'cpp', + version: '1.0.0', + default_options: ['cpp_std=c++17'] + ) + + +jsoncdep = dependency('json-c') + +mesonexlib = shared_library('mesonexlib', + 'cpp-example-lib.cpp', 'cpp-example-lib.hpp', + version: meson.project_version(), + soversion: meson.project_version().split('.')[0], + dependencies : jsoncdep, + install : true + ) + +executable('mesonex', + 'cpp-example.cpp', + link_with : mesonexlib, + install : true + ) + +test_mesonex = executable('test-mesonex', + 'test-cpp-example.cpp', + link_with : mesonexlib, + install : true +) +test('meson example test', test_mesonex) diff --git a/meta-selftest/recipes-test/cpp/files/test-cpp-example.cpp b/meta-selftest/recipes-test/cpp/files/test-cpp-example.cpp new file mode 100644 index 00000000000..ca72e11a9c4 --- /dev/null +++ b/meta-selftest/recipes-test/cpp/files/test-cpp-example.cpp @@ -0,0 +1,19 @@ +/* +* Copyright OpenEmbedded Contributors +* +* SPDX-License-Identifier: MIT +*/ + +#include "cpp-example-lib.hpp" + +#include + +int main() { + auto cpp_example = CppExample(); + auto ret_string = cpp_example.get_string(); + if(0 == ret_string.compare(CppExample::test_string)) { + std::cout << "PASS: " << ret_string << " = " << CppExample::test_string << std::endl; + } else { + std::cout << "FAIL: " << ret_string << " != " << CppExample::test_string << std::endl; + } +} diff --git a/meta-selftest/recipes-test/cpp/meson-example.bb b/meta-selftest/recipes-test/cpp/meson-example.bb new file mode 100644 index 00000000000..f15dbb50731 --- /dev/null +++ b/meta-selftest/recipes-test/cpp/meson-example.bb @@ -0,0 +1,17 @@ +# +# Copyright OpenEmbedded Contributors +# +# SPDX-License-Identifier: MIT +# + +SUMMARY = "A C++ example compiled with meson." + +inherit pkgconfig meson + +require cpp-example.inc + +SRC_URI += "\ + file://meson.build \ +" + +FILES:${PN}-ptest += "${bindir}/test-mesonex" diff --git a/meta-selftest/recipes-test/cpp/meson-example/run-ptest b/meta-selftest/recipes-test/cpp/meson-example/run-ptest new file mode 100644 index 00000000000..b1804f00961 --- /dev/null +++ b/meta-selftest/recipes-test/cpp/meson-example/run-ptest @@ -0,0 +1,10 @@ +#!/bin/sh +# +# Copyright OpenEmbedded Contributors +# +# SPDX-License-Identifier: MIT +# + +test-mesonex + +# Note: run-ptests exits with exit value from test-mesonex From patchwork Sun Sep 10 15:52:31 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adrian Freihofer X-Patchwork-Id: 30256 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 BCDAFEEB590 for ; Sun, 10 Sep 2023 16:19:29 +0000 (UTC) Received: from mail-wr1-f53.google.com (mail-wr1-f53.google.com [209.85.221.53]) by mx.groups.io with SMTP id smtpd.web10.39054.1694362764685517392 for ; Sun, 10 Sep 2023 09:19:24 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20221208 header.b=Y13rl4Ik; spf=pass (domain: gmail.com, ip: 209.85.221.53, mailfrom: adrian.freihofer@gmail.com) Received: by mail-wr1-f53.google.com with SMTP id ffacd0b85a97d-31dca134c83so3629164f8f.3 for ; Sun, 10 Sep 2023 09:19:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1694362763; x=1694967563; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=r/JU2AOFiMtjJt9nxjy8Xjf4md5X6Dyo8Xa9UuZQhDM=; b=Y13rl4Ikgaj1RRl4JzQSgfRrAow38fn52O7QAQM9MSCHVtLrVF+HyYhn/Ci5zyL8Kl /jX6BOAnwJgchkXA8tPgmw9K3grAen7kwfpZ2kJk2gtEOXO21c8sjZSVpzpItQcT6fF1 8mapWzFG58DWKqXCrnX3MkOiA1GjBEMCsEhPRcWn8qR0ZzHLdozTC0dGjVDNG5kXEu5V Zfdntc3qYC0brnA65fT+/C2OUpxBbEhwT+fNFVqcO+cVGq2OEdaC7lTPALGHy5ldtUAt 7jf/SpbF/8L4Mz8jsG3uX1Las5HZpbPu/CZWwM3klNPUp0Q5aS3P43r826Bv56FF1QE1 KJ5g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1694362763; x=1694967563; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=r/JU2AOFiMtjJt9nxjy8Xjf4md5X6Dyo8Xa9UuZQhDM=; b=WVplonVc77ny6UK6MgyAV8XLAwK9G5dUEAvKxHqCgj645c9wpSLQgy4av32Ppi69Wh EbssqgibSq7B2Eyua0EKZpbRECBpbNTgdQeCldrsbH6Xm7YNsUrxAbAXJHO1iM4BnfVv tIFNKCoY5HOsID5M+OB+ayBxlfBj00Hut4ot9cOlbtCHs/C3r2Fi3yPir6I5meOtqnG2 JSX5Wcu9bi1BbvqNqgPumbYHjxCZ1P5oO6vvrOQQ4BYLHZksbOU7+BngcMHrdk3EtL4E Zdwq5fNLJct221MxS6dy+K9uZOeHzPX0syqaWj8MtUtwfcTNHSHgub9HCvh2fdQaodu+ mrfA== X-Gm-Message-State: AOJu0Yz7HDp86khOPYc0yhUsMpsP417juBSu37aDkkzFgBrCS/lpLV3K oxzeb3gmA0hxchZEVP+lxBr8Rttbzfw= X-Google-Smtp-Source: AGHT+IEbfD15/Q0SSWJLfhRgl/dwePK9BisAW6LgGgTIC5NUKjIn5exHOdfJgQA5zhe4VJJkAiNh3g== X-Received: by 2002:a5d:65c5:0:b0:314:3bd7:6a0c with SMTP id e5-20020a5d65c5000000b003143bd76a0cmr5187736wrw.33.1694362762907; Sun, 10 Sep 2023 09:19:22 -0700 (PDT) Received: from t14s-af.fritz.box ([2a02:169:59a6:0:dcf2:2f65:9442:83f]) by smtp.gmail.com with ESMTPSA id o12-20020a5d408c000000b003142ea7a661sm7605431wrp.21.2023.09.10.09.19.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 Sep 2023 09:19:22 -0700 (PDT) From: Adrian Freihofer X-Google-Original-From: Adrian Freihofer To: openembedded-core@lists.openembedded.org Cc: Adrian Freihofer Subject: [OE-core][PATCH v6 05/12] cpp-example: workaround for pseudo breakeage Date: Sun, 10 Sep 2023 17:52:31 +0200 Message-ID: <20230910161850.4032227-6-adrian.freihofer@siemens.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230910161850.4032227-1-adrian.freihofer@siemens.com> References: <20230910161850.4032227-1-adrian.freihofer@siemens.com> MIME-Version: 1.0 List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Sun, 10 Sep 2023 16:19:29 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/187463 Signed-off-by: Adrian Freihofer --- meta-selftest/recipes-test/cpp/cmake-example.bb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/meta-selftest/recipes-test/cpp/cmake-example.bb b/meta-selftest/recipes-test/cpp/cmake-example.bb index 96d543180b4..fbf1f266721 100644 --- a/meta-selftest/recipes-test/cpp/cmake-example.bb +++ b/meta-selftest/recipes-test/cpp/cmake-example.bb @@ -15,3 +15,9 @@ SRC_URI += "\ " FILES:${PN}-ptest += "${bindir}/test-cmake-example" + +# This is a workaround for packages with sources in-tree +# Without this bitbake ... does not work after running the install script. +# newenv['PSEUDO_IGNORE_PATHS'] = newenv['PSEUDO_IGNORE_PATHS'] + "" +# path mismatch [3 links]: ino 37529096 db '/home/adrian/projects/oss/meta-yocto-upstream/projects/poky-oe-glibc-sd/tmp/work/cortexa57-poky-linux/cmake-example/1.0-r0/package/usr/src/debug/cmake-example/1.0-r0/oe-local-files/cmake-example-lib.cpp' req '/home/adrian/projects/oss/meta-yocto-upstream/projects/poky-oe-glibc-sd/workspace/sources/cmake-example/oe-local-files/cmake-example-lib.cpp'. +PACKAGE_DEBUG_SPLIT_STYLE = "debug-without-src" From patchwork Sun Sep 10 15:52:32 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adrian Freihofer X-Patchwork-Id: 30254 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 BCD36EEB580 for ; Sun, 10 Sep 2023 16:19:29 +0000 (UTC) Received: from mail-wr1-f42.google.com (mail-wr1-f42.google.com [209.85.221.42]) by mx.groups.io with SMTP id smtpd.web11.39125.1694362765860028984 for ; Sun, 10 Sep 2023 09:19:26 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20221208 header.b=YXFHu/e9; spf=pass (domain: gmail.com, ip: 209.85.221.42, mailfrom: adrian.freihofer@gmail.com) Received: by mail-wr1-f42.google.com with SMTP id ffacd0b85a97d-317c3ac7339so3380524f8f.0 for ; Sun, 10 Sep 2023 09:19:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1694362764; x=1694967564; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=0KCvk2S8+R6M1hUYSU09U95QEnD4CiRS6l5BrjJwoc0=; b=YXFHu/e9Qdvsh1qv5SpLTYNl+ddAatnlOW+nfM3IS/k1Z1jyonEJ6xbC62hPng8jcA mQMHnKe5FmI19pvOpG6souxy+KVgrheXRKSQo9Gc89gYukr3H/t1tPRdChHgSuKWFoM2 Dj290aVlPCiT3+oCNxRlPTdsel97SW9hV1S0eQq1hBMpU3xVEUGL7x4t/1KdvVLLN5k+ 761UrMYDM2csEazM5erh0vNhi0rRclxjJS1v4u5/TyMf83scK64F4vlImr/DbK12I7Zh Qv+hMU+c43Fd1wn7z7rEOk9zVXvoY9voSrylCTkLzy8ZQ2AdpkqXWSonxuzdDflOEfIc IF3A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1694362764; x=1694967564; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=0KCvk2S8+R6M1hUYSU09U95QEnD4CiRS6l5BrjJwoc0=; b=DgNbG6F4+Li6X3RACrgSnOlHz40cyt7Zqo01F9WBgDCLTF3F+Lz1U/9ECobDDqqyMO X6G1OI/H8n0vbCHwA1p+W7fAR09bx5Qg1roWFyzfpxXaaDzrf0bg7gwHczT6+TXztgPu kbfN0FLxmVAkWsj2sKoNTyZOcJMXJBXO/qeN1hbyeFmt42igur9Qjfm8Tz62zCct3rsx 8O2PTkC4M3B4hhqyDM/HKbq+YDS6/BAtkUo8LaBzd2ZdlHDIkkvRgTQzcok64uOvoaUT pm/W/pXwGQlXg/L4756uEnsEWzjBWlKViN0zF8ZE4HQquiMN3ksNgaIcWMaNzIYLTixm J6Bg== X-Gm-Message-State: AOJu0YxRS9+LdJmREZ3VK3Dp0uoP8+jI1LEJj5+mLNmEU81D6KvLOQZh JaID0/ZzTfjlW82ZKRHqiMDgOv0xXQI= X-Google-Smtp-Source: AGHT+IE56TtigQBMBHq9liXFu9wuAWyhS4ezW9VhrIQQsZe8tLL9Dq9xyt6uT3xYZf5toadw8Zonmw== X-Received: by 2002:adf:ec4c:0:b0:313:ef08:c83b with SMTP id w12-20020adfec4c000000b00313ef08c83bmr5456797wrn.56.1694362763760; Sun, 10 Sep 2023 09:19:23 -0700 (PDT) Received: from t14s-af.fritz.box ([2a02:169:59a6:0:dcf2:2f65:9442:83f]) by smtp.gmail.com with ESMTPSA id o12-20020a5d408c000000b003142ea7a661sm7605431wrp.21.2023.09.10.09.19.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 Sep 2023 09:19:23 -0700 (PDT) From: Adrian Freihofer X-Google-Original-From: Adrian Freihofer To: openembedded-core@lists.openembedded.org Cc: Adrian Freihofer Subject: [OE-core][PATCH v6 06/12] refactor: make multiprocess_launch callable without d Date: Sun, 10 Sep 2023 17:52:32 +0200 Message-ID: <20230910161850.4032227-7-adrian.freihofer@siemens.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230910161850.4032227-1-adrian.freihofer@siemens.com> References: <20230910161850.4032227-1-adrian.freihofer@siemens.com> MIME-Version: 1.0 List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Sun, 10 Sep 2023 16:19:29 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/187464 This is a preparation for making the strip_execs function callable from devtool without going via tinfoil and a bitbake server process. Signed-off-by: Adrian Freihofer --- meta/conf/bitbake.conf | 2 +- meta/lib/oe/utils.py | 12 +++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/meta/conf/bitbake.conf b/meta/conf/bitbake.conf index 0bcc8215c5d..69e854ecedc 100644 --- a/meta/conf/bitbake.conf +++ b/meta/conf/bitbake.conf @@ -975,5 +975,5 @@ BB_UNIHASH ?= "${BB_TASKHASH}" oe.sstatesig.find_sstate_manifest[vardepsexclude] = "BBEXTENDCURR BBEXTENDVARIANT OVERRIDES PACKAGE_EXTRA_ARCHS" oe.utils.get_multilib_datastore[vardepsexclude] = "DEFAULTTUNE_MULTILIB_ORIGINAL OVERRIDES" oe.path.format_display[vardepsexclude] = "TOPDIR" -oe.utils.multiprocess_launch[vardepsexclude] = "BB_NUMBER_THREADS" +oe.utils.get_bb_number_threads[vardepsexclude] = "BB_NUMBER_THREADS" oe.packagedata.emit_pkgdata[vardepsexclude] = "BB_NUMBER_THREADS" diff --git a/meta/lib/oe/utils.py b/meta/lib/oe/utils.py index 1658f3555d3..a3b1bb1087d 100644 --- a/meta/lib/oe/utils.py +++ b/meta/lib/oe/utils.py @@ -264,10 +264,17 @@ def execute_pre_post_process(d, cmds): bb.note("Executing %s ..." % cmd) bb.build.exec_func(cmd, d) -# For each item in items, call the function 'target' with item as the first +def get_bb_number_threads(d): + return int(d.getVar("BB_NUMBER_THREADS") or os.cpu_count() or 1) + +def multiprocess_launch(target, items, d, extraargs=None): + max_process = get_bb_number_threads(d) + return multiprocess_launch_mp(target, items, max_process, extraargs) + +# For each item in items, call the function 'target' with item as the first # argument, extraargs as the other arguments and handle any exceptions in the # parent thread -def multiprocess_launch(target, items, d, extraargs=None): +def multiprocess_launch_mp(target, items, max_process, extraargs=None): class ProcessLaunch(multiprocessing.Process): def __init__(self, *args, **kwargs): @@ -302,7 +309,6 @@ def multiprocess_launch(target, items, d, extraargs=None): self.update() return self._result - max_process = int(d.getVar("BB_NUMBER_THREADS") or os.cpu_count() or 1) launched = [] errors = [] results = [] From patchwork Sun Sep 10 15:52:33 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adrian Freihofer X-Patchwork-Id: 30257 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 CD743EEB58F for ; Sun, 10 Sep 2023 16:19:29 +0000 (UTC) Received: from mail-wr1-f42.google.com (mail-wr1-f42.google.com [209.85.221.42]) by mx.groups.io with SMTP id smtpd.web11.39126.1694362766328156304 for ; Sun, 10 Sep 2023 09:19:26 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20221208 header.b=JLsikuI6; spf=pass (domain: gmail.com, ip: 209.85.221.42, mailfrom: adrian.freihofer@gmail.com) Received: by mail-wr1-f42.google.com with SMTP id ffacd0b85a97d-31f71b25a99so3308103f8f.2 for ; Sun, 10 Sep 2023 09:19:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1694362764; x=1694967564; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=7c86nxg2BMAsLSg0HXWALOut08e2w5F1zYwmYIPR1IE=; b=JLsikuI6yiV6CXPGQPVvfzqRlEugbPoOTKzvFdhwziA1hppxeZI4uZ+u4cAV7AcfPy v7W7NjguFG9vz3pnvrH1Mw5Y7ulYAEfWxwltIupTbtuku5UnvuYD2FqvG+lS2raijksa wQuk893soPtXA6OV2YU+p2hWOvGtBnwq3FfgvgmHue0UQ380199ZbWluE8uAvbxStS2B qkMj8AKtk0jNCBXB4WvgkFLkPLO4Dahc9Bq4RKYbUOXcUdzGypgEl+h5ZwWco03+NmmJ lhKwNl28ns/94kL2VUjpefnQPbtbsMUdhIyzoTbesvvCthJLSycXEnu0J2apcPDqt2+V eW2Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1694362764; x=1694967564; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=7c86nxg2BMAsLSg0HXWALOut08e2w5F1zYwmYIPR1IE=; b=lHNEG/n5gdV0LHIcT76+A7H2jRvlfVUI/cgzuqdUMJj8ETQlRels6z7jVWVJ/crKW3 G5c6GCOI9Lp1nu5SckIeRJjInDGYscAm5WFJ6rCsZvaz2hrBzP8acdnhR5z5bqanHJZ9 1vL9sEh+Tx7IRmPo64JuJgLI/7NBGqDBJvDDCSw61eUIlFYhcihAajZJNqcAWQD8wtBk Im9Dtk0ZBkzKDDtzjZDpDyPmFGXm/vygHWNXv/fWmfuu48iczD1ZvClXx5wZei9O9TFY pbpRILdrboW5uoK/ySvqZWbYCG3c7x7xyASkztwytBcFmaVH4cYYIV/7j1C51hoSyLE4 0V3w== X-Gm-Message-State: AOJu0YzRhVfbuTK0DVD0vA9790V4DNNHtFA1uZux7s9YcAMQe0Lz3DCe 9AzJ9iwEu4i+5skKxtbJPnWHuLfvO4k= X-Google-Smtp-Source: AGHT+IGA9HTc5Dntbc3j04rvdVDME/bbDzE+dxbWUp1HwNNM2Ll0KBKsy+hmkV/QBjisz/U2lF66fQ== X-Received: by 2002:adf:cc86:0:b0:317:5722:a41b with SMTP id p6-20020adfcc86000000b003175722a41bmr5665656wrj.7.1694362764600; Sun, 10 Sep 2023 09:19:24 -0700 (PDT) Received: from t14s-af.fritz.box ([2a02:169:59a6:0:dcf2:2f65:9442:83f]) by smtp.gmail.com with ESMTPSA id o12-20020a5d408c000000b003142ea7a661sm7605431wrp.21.2023.09.10.09.19.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 Sep 2023 09:19:24 -0700 (PDT) From: Adrian Freihofer X-Google-Original-From: Adrian Freihofer To: openembedded-core@lists.openembedded.org Cc: Adrian Freihofer Subject: [OE-core][PATCH v6 07/12] refactor: make strip_execs callable without d Date: Sun, 10 Sep 2023 17:52:33 +0200 Message-ID: <20230910161850.4032227-8-adrian.freihofer@siemens.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230910161850.4032227-1-adrian.freihofer@siemens.com> References: <20230910161850.4032227-1-adrian.freihofer@siemens.com> MIME-Version: 1.0 List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Sun, 10 Sep 2023 16:19:29 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/187465 This allows to call strip_execs function from devtool without going via tinfoil and a bitbake server process. Signed-off-by: Adrian Freihofer --- meta/classes-global/staging.bbclass | 3 ++- meta/lib/oe/package.py | 7 ++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/meta/classes-global/staging.bbclass b/meta/classes-global/staging.bbclass index 3a300c32e7c..d229f401073 100644 --- a/meta/classes-global/staging.bbclass +++ b/meta/classes-global/staging.bbclass @@ -92,7 +92,8 @@ python sysroot_strip () { qa_already_stripped = 'already-stripped' in (d.getVar('INSANE_SKIP:' + pn) or "").split() strip_cmd = d.getVar("STRIP") - oe.package.strip_execs(pn, dstdir, strip_cmd, libdir, base_libdir, d, + max_process = oe.utils.get_bb_number_threads(d) + oe.package.strip_execs(pn, dstdir, strip_cmd, libdir, base_libdir, max_process, qa_already_stripped=qa_already_stripped) } diff --git a/meta/lib/oe/package.py b/meta/lib/oe/package.py index 9d70925b9b7..1dd20f85ebd 100644 --- a/meta/lib/oe/package.py +++ b/meta/lib/oe/package.py @@ -114,7 +114,7 @@ def is_static_lib(path): return start == magic return False -def strip_execs(pn, dstdir, strip_cmd, libdir, base_libdir, d, qa_already_stripped=False): +def strip_execs(pn, dstdir, strip_cmd, libdir, base_libdir, max_process, qa_already_stripped=False): """ Strip executable code (like executables, shared libraries) _in_place_ - Based on sysroot_strip in staging.bbclass @@ -122,6 +122,7 @@ def strip_execs(pn, dstdir, strip_cmd, libdir, base_libdir, d, qa_already_stripp :param strip_cmd: Strip command (usually ${STRIP}) :param libdir: ${libdir} - strip .so files in this directory :param base_libdir: ${base_libdir} - strip .so files in this directory + :param max_process: number of stripping processes started in parallel :param qa_already_stripped: Set to True if already-stripped' in ${INSANE_SKIP} This is for proper logging and messages only. """ @@ -164,7 +165,7 @@ def strip_execs(pn, dstdir, strip_cmd, libdir, base_libdir, d, qa_already_stripp # ...but is it ELF, and is it already stripped? checkelf.append(file) inodecache[file] = s.st_ino - results = oe.utils.multiprocess_launch(is_elf, checkelf, d) + results = oe.utils.multiprocess_launch_mp(is_elf, checkelf, max_process) for (file, elf_file) in results: #elf_file = is_elf(file) if elf_file & 1: @@ -192,7 +193,7 @@ def strip_execs(pn, dstdir, strip_cmd, libdir, base_libdir, d, qa_already_stripp elf_file = int(elffiles[file]) sfiles.append((file, elf_file, strip_cmd)) - oe.utils.multiprocess_launch(runstrip, sfiles, d) + oe.utils.multiprocess_launch_mp(runstrip, sfiles, max_process) def file_translate(file): From patchwork Sun Sep 10 15:52:34 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adrian Freihofer X-Patchwork-Id: 30261 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 DDA46EEB592 for ; Sun, 10 Sep 2023 16:19:29 +0000 (UTC) Received: from mail-wr1-f50.google.com (mail-wr1-f50.google.com [209.85.221.50]) by mx.groups.io with SMTP id smtpd.web10.39056.1694362767447325430 for ; Sun, 10 Sep 2023 09:19:27 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20221208 header.b=VWlaHmN4; spf=pass (domain: gmail.com, ip: 209.85.221.50, mailfrom: adrian.freihofer@gmail.com) Received: by mail-wr1-f50.google.com with SMTP id ffacd0b85a97d-31fa666000dso220265f8f.2 for ; Sun, 10 Sep 2023 09:19:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1694362765; x=1694967565; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Jy8i1/A44FHlgQLN08tx4d2NioWfPZimdixvZe0CbjI=; b=VWlaHmN48h4YMTO5zTq1qLlCMJL0FEwQe2mJSnw9dsuOzNhkMZ9xQ6z7UdRpHkrkBQ Fg5+7uDpECHtY7wG18CdtHPLTliLKWDqtID2TeTxZSnoX+K3kBan5N8voaM9fRtmuK7K 9OLEH6xk5AfnSAXR3/wzoypaSgS1BZrLZWRZuqDuJeAfl+q8UscUTKH99Ruon5CTP/ni 2KCKjTw6bM0FXsbZ7cX5wGUATqkmXZXc+tERFT63Y+sXamFa2h8s3DI24QRIuydW9hGx PgSVNZh5Mxy/70lXB52gpnqRUqzl9nS+c7YuN1SIFKOt2kPlp3lJljjFVzI3ri/p44DT 7cPQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1694362765; x=1694967565; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Jy8i1/A44FHlgQLN08tx4d2NioWfPZimdixvZe0CbjI=; b=VKcuIz/cD3U60ckoe3cmcj4yt7jX5PBrV1WBf8MqraF/bvD64vsQ+YDiDVmvgaV6XG FMzeVZ/6jFUqkVJ1mXcdr+mwJ5sA90F+uNfJSeWPUF+z7hiRWKMzOJrnhFXfTNiw0C9N nltrOhrjIbWul7khlnBCmM1njR/WjDrHzEpZnR8r6C4QteMC3XJvM7IKnMOIYhYVa3zF +0ms1UBB2sfrxkIjz9zhKdidgHni7kpAe4odlZ/Uc5ftNDsdHF2Me/5Z8jpVTqTaInf3 CUR8/5RI0jA9MgbDdqNE91QQsSApkHklY0I1Opz912mv+K7cLIMmvNNzkhq41MxFYMvp EHLQ== X-Gm-Message-State: AOJu0Yw8tKvdsCo96V+bkjf5+9dgEujb4+1oYf5GRTuY4VmALmnqPxhx ljz0Uh9VAzb6eN+Luotv6RfbnpAL/bk= X-Google-Smtp-Source: AGHT+IFwviUZeCpR14KBtTDdtN8zKsu/EDxnDBtQQKLOuhX6r+dIsPPmfWnO8dhcsp1Yk2i1M2aU3Q== X-Received: by 2002:adf:ab11:0:b0:31f:8e7c:6ebe with SMTP id q17-20020adfab11000000b0031f8e7c6ebemr3028984wrc.5.1694362765522; Sun, 10 Sep 2023 09:19:25 -0700 (PDT) Received: from t14s-af.fritz.box ([2a02:169:59a6:0:dcf2:2f65:9442:83f]) by smtp.gmail.com with ESMTPSA id o12-20020a5d408c000000b003142ea7a661sm7605431wrp.21.2023.09.10.09.19.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 Sep 2023 09:19:25 -0700 (PDT) From: Adrian Freihofer X-Google-Original-From: Adrian Freihofer To: openembedded-core@lists.openembedded.org Cc: Adrian Freihofer Subject: [OE-core][PATCH v6 08/12] devtool: refactor deploy-target Date: Sun, 10 Sep 2023 17:52:34 +0200 Message-ID: <20230910161850.4032227-9-adrian.freihofer@siemens.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230910161850.4032227-1-adrian.freihofer@siemens.com> References: <20230910161850.4032227-1-adrian.freihofer@siemens.com> MIME-Version: 1.0 List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Sun, 10 Sep 2023 16:19:29 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/187466 Signed-off-by: Adrian Freihofer --- scripts/lib/devtool/__init__.py | 5 +- scripts/lib/devtool/deploy.py | 230 +++++++++++++++++--------------- 2 files changed, 124 insertions(+), 111 deletions(-) diff --git a/scripts/lib/devtool/__init__.py b/scripts/lib/devtool/__init__.py index 702db669de3..7d64547616e 100644 --- a/scripts/lib/devtool/__init__.py +++ b/scripts/lib/devtool/__init__.py @@ -78,12 +78,15 @@ def exec_fakeroot(d, cmd, **kwargs): """Run a command under fakeroot (pseudo, in fact) so that it picks up the appropriate file permissions""" # Grab the command and check it actually exists fakerootcmd = d.getVar('FAKEROOTCMD') + fakerootenv = d.getVar('FAKEROOTENV') + exec_fakeroot_no_d(fakerootcmd, fakerootenv, cmd, kwargs) + +def exec_fakeroot_no_d(fakerootcmd, fakerootenv, cmd, **kwargs): if not os.path.exists(fakerootcmd): logger.error('pseudo executable %s could not be found - have you run a build yet? pseudo-native should install this and if you have run any build then that should have been built') return 2 # Set up the appropriate environment newenv = dict(os.environ) - fakerootenv = d.getVar('FAKEROOTENV') for varvalue in fakerootenv.split(): if '=' in varvalue: splitval = varvalue.split('=', 1) diff --git a/scripts/lib/devtool/deploy.py b/scripts/lib/devtool/deploy.py index e14a5874177..ea7e2cb1ae8 100644 --- a/scripts/lib/devtool/deploy.py +++ b/scripts/lib/devtool/deploy.py @@ -16,7 +16,7 @@ import bb.utils import argparse_oe import oe.types -from devtool import exec_fakeroot, setup_tinfoil, check_workspace_recipe, DevtoolError +from devtool import exec_fakeroot_no_d, setup_tinfoil, check_workspace_recipe, DevtoolError logger = logging.getLogger('devtool') @@ -133,16 +133,11 @@ def _prepare_remote_script(deploy, verbose=False, dryrun=False, undeployall=Fals return '\n'.join(lines) - - -def deploy(args, config, basepath, workspace): - """Entry point for the devtool 'deploy' subcommand""" +def deploy_cached(srcdir, workdir, path, strip_cmd, libdir, base_libdir, max_process, fakerootcmd, fakerootenv, args): import math import oe.recipeutils import oe.package - check_workspace_recipe(workspace, args.recipename, checksrc=False) - try: host, destdir = args.target.split(':') except ValueError: @@ -152,116 +147,131 @@ def deploy(args, config, basepath, workspace): if not destdir.endswith('/'): destdir += '/' + recipe_outdir = srcdir + if not os.path.exists(recipe_outdir) or not os.listdir(recipe_outdir): + raise DevtoolError('No files to deploy - have you built the %s ' + 'recipe? If so, the install step has not installed ' + 'any files.' % args.recipename) + + if args.strip and not args.dry_run: + # Fakeroot copy to new destination + srcdir = recipe_outdir + recipe_outdir = os.path.join(workdir, 'devtool-deploy-target-stripped') + if os.path.isdir(recipe_outdir): + exec_fakeroot_no_d(fakerootcmd, fakerootenv, "rm -rf %s" % recipe_outdir, shell=True) + exec_fakeroot_no_d(fakerootcmd, fakerootenv, "cp -af %s %s" % (os.path.join(srcdir, '.'), recipe_outdir), shell=True) + os.environ['PATH'] = ':'.join([os.environ['PATH'], path or '']) + oe.package.strip_execs(args.recipename, recipe_outdir, strip_cmd, libdir, base_libdir, max_process) + + filelist = [] + inodes = set({}) + ftotalsize = 0 + for root, _, files in os.walk(recipe_outdir): + for fn in files: + fstat = os.lstat(os.path.join(root, fn)) + # Get the size in kiB (since we'll be comparing it to the output of du -k) + # MUST use lstat() here not stat() or getfilesize() since we don't want to + # dereference symlinks + if fstat.st_ino in inodes: + fsize = 0 + else: + fsize = int(math.ceil(float(fstat.st_size)/1024)) + inodes.add(fstat.st_ino) + ftotalsize += fsize + # The path as it would appear on the target + fpath = os.path.join(destdir, os.path.relpath(root, recipe_outdir), fn) + filelist.append((fpath, fsize)) + + if args.dry_run: + print('Files to be deployed for %s on target %s:' % (args.recipename, args.target)) + for item, _ in filelist: + print(' %s' % item) + return 0 + + extraoptions = '' + if args.no_host_check: + extraoptions += '-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no' + if not args.show_status: + extraoptions += ' -q' + + scp_sshexec = '' + ssh_sshexec = 'ssh' + if args.ssh_exec: + scp_sshexec = "-S %s" % args.ssh_exec + ssh_sshexec = args.ssh_exec + scp_port = '' + ssh_port = '' + if args.port: + scp_port = "-P %s" % args.port + ssh_port = "-p %s" % args.port + + if args.key: + extraoptions += ' -i %s' % args.key + + # In order to delete previously deployed files and have the manifest file on + # the target, we write out a shell script and then copy it to the target + # so we can then run it (piping tar output to it). + # (We cannot use scp here, because it doesn't preserve symlinks.) + tmpdir = tempfile.mkdtemp(prefix='devtool') + try: + tmpscript = '/tmp/devtool_deploy.sh' + tmpfilelist = os.path.join(os.path.dirname(tmpscript), 'devtool_deploy.list') + shellscript = _prepare_remote_script(deploy=True, + verbose=args.show_status, + nopreserve=args.no_preserve, + nocheckspace=args.no_check_space) + # Write out the script to a file + with open(os.path.join(tmpdir, os.path.basename(tmpscript)), 'w') as f: + f.write(shellscript) + # Write out the file list + with open(os.path.join(tmpdir, os.path.basename(tmpfilelist)), 'w') as f: + f.write('%d\n' % ftotalsize) + for fpath, fsize in filelist: + f.write('%s %d\n' % (fpath, fsize)) + # Copy them to the target + ret = subprocess.call("scp %s %s %s %s/* %s:%s" % (scp_sshexec, scp_port, extraoptions, tmpdir, args.target, os.path.dirname(tmpscript)), shell=True) + if ret != 0: + raise DevtoolError('Failed to copy script to %s - rerun with -s to ' + 'get a complete error message' % args.target) + finally: + shutil.rmtree(tmpdir) + + # Now run the script + ret = exec_fakeroot_no_d(fakerootcmd, fakerootenv, 'tar cf - . | %s %s %s %s \'sh %s %s %s %s\'' % (ssh_sshexec, ssh_port, extraoptions, args.target, tmpscript, args.recipename, destdir, tmpfilelist), cwd=recipe_outdir, shell=True) + if ret != 0: + raise DevtoolError('Deploy failed - rerun with -s to get a complete ' + 'error message') + + logger.info('Successfully deployed %s' % recipe_outdir) + + files_list = [] + for root, _, files in os.walk(recipe_outdir): + for filename in files: + filename = os.path.relpath(os.path.join(root, filename), recipe_outdir) + files_list.append(os.path.join(destdir, filename)) + +def deploy(args, config, basepath, workspace): + """Entry point for the devtool 'deploy' subcommand""" + check_workspace_recipe(workspace, args.recipename, checksrc=False) + tinfoil = setup_tinfoil(basepath=basepath) try: try: rd = tinfoil.parse_recipe(args.recipename) + + srcdir = rd.getVar('D') + workdir = rd.getVar('WORKDIR') + path = rd.getVar('PATH') + strip_cmd = rd.getVar('STRIP') + libdir = rd.getVar('libdir'), + base_libdir = rd.getVar('base_libdir') + max_process = int(rd.getVar("BB_NUMBER_THREADS") or os.cpu_count() or 1) + fakerootcmd = rd.getVar('FAKEROOTCMD') + fakerootenv = rd.getVar('FAKEROOTENV') + deploy_cached(srcdir, workdir, path, strip_cmd, libdir, base_libdir, max_process, fakerootcmd, fakerootenv, args) except Exception as e: raise DevtoolError('Exception parsing recipe %s: %s' % (args.recipename, e)) - recipe_outdir = rd.getVar('D') - if not os.path.exists(recipe_outdir) or not os.listdir(recipe_outdir): - raise DevtoolError('No files to deploy - have you built the %s ' - 'recipe? If so, the install step has not installed ' - 'any files.' % args.recipename) - - if args.strip and not args.dry_run: - # Fakeroot copy to new destination - srcdir = recipe_outdir - recipe_outdir = os.path.join(rd.getVar('WORKDIR'), 'devtool-deploy-target-stripped') - if os.path.isdir(recipe_outdir): - exec_fakeroot(rd, "rm -rf %s" % recipe_outdir, shell=True) - exec_fakeroot(rd, "cp -af %s %s" % (os.path.join(srcdir, '.'), recipe_outdir), shell=True) - os.environ['PATH'] = ':'.join([os.environ['PATH'], rd.getVar('PATH') or '']) - oe.package.strip_execs(args.recipename, recipe_outdir, rd.getVar('STRIP'), rd.getVar('libdir'), - rd.getVar('base_libdir'), rd) - - filelist = [] - inodes = set({}) - ftotalsize = 0 - for root, _, files in os.walk(recipe_outdir): - for fn in files: - fstat = os.lstat(os.path.join(root, fn)) - # Get the size in kiB (since we'll be comparing it to the output of du -k) - # MUST use lstat() here not stat() or getfilesize() since we don't want to - # dereference symlinks - if fstat.st_ino in inodes: - fsize = 0 - else: - fsize = int(math.ceil(float(fstat.st_size)/1024)) - inodes.add(fstat.st_ino) - ftotalsize += fsize - # The path as it would appear on the target - fpath = os.path.join(destdir, os.path.relpath(root, recipe_outdir), fn) - filelist.append((fpath, fsize)) - - if args.dry_run: - print('Files to be deployed for %s on target %s:' % (args.recipename, args.target)) - for item, _ in filelist: - print(' %s' % item) - return 0 - - extraoptions = '' - if args.no_host_check: - extraoptions += '-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no' - if not args.show_status: - extraoptions += ' -q' - - scp_sshexec = '' - ssh_sshexec = 'ssh' - if args.ssh_exec: - scp_sshexec = "-S %s" % args.ssh_exec - ssh_sshexec = args.ssh_exec - scp_port = '' - ssh_port = '' - if args.port: - scp_port = "-P %s" % args.port - ssh_port = "-p %s" % args.port - - if args.key: - extraoptions += ' -i %s' % args.key - - # In order to delete previously deployed files and have the manifest file on - # the target, we write out a shell script and then copy it to the target - # so we can then run it (piping tar output to it). - # (We cannot use scp here, because it doesn't preserve symlinks.) - tmpdir = tempfile.mkdtemp(prefix='devtool') - try: - tmpscript = '/tmp/devtool_deploy.sh' - tmpfilelist = os.path.join(os.path.dirname(tmpscript), 'devtool_deploy.list') - shellscript = _prepare_remote_script(deploy=True, - verbose=args.show_status, - nopreserve=args.no_preserve, - nocheckspace=args.no_check_space) - # Write out the script to a file - with open(os.path.join(tmpdir, os.path.basename(tmpscript)), 'w') as f: - f.write(shellscript) - # Write out the file list - with open(os.path.join(tmpdir, os.path.basename(tmpfilelist)), 'w') as f: - f.write('%d\n' % ftotalsize) - for fpath, fsize in filelist: - f.write('%s %d\n' % (fpath, fsize)) - # Copy them to the target - ret = subprocess.call("scp %s %s %s %s/* %s:%s" % (scp_sshexec, scp_port, extraoptions, tmpdir, args.target, os.path.dirname(tmpscript)), shell=True) - if ret != 0: - raise DevtoolError('Failed to copy script to %s - rerun with -s to ' - 'get a complete error message' % args.target) - finally: - shutil.rmtree(tmpdir) - - # Now run the script - ret = exec_fakeroot(rd, 'tar cf - . | %s %s %s %s \'sh %s %s %s %s\'' % (ssh_sshexec, ssh_port, extraoptions, args.target, tmpscript, args.recipename, destdir, tmpfilelist), cwd=recipe_outdir, shell=True) - if ret != 0: - raise DevtoolError('Deploy failed - rerun with -s to get a complete ' - 'error message') - - logger.info('Successfully deployed %s' % recipe_outdir) - - files_list = [] - for root, _, files in os.walk(recipe_outdir): - for filename in files: - filename = os.path.relpath(os.path.join(root, filename), recipe_outdir) - files_list.append(os.path.join(destdir, filename)) finally: tinfoil.shutdown() From patchwork Sun Sep 10 15:52:35 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adrian Freihofer X-Patchwork-Id: 30260 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 DF784EEB593 for ; Sun, 10 Sep 2023 16:19:29 +0000 (UTC) Received: from mail-wr1-f43.google.com (mail-wr1-f43.google.com [209.85.221.43]) by mx.groups.io with SMTP id smtpd.web10.39057.1694362768168011868 for ; Sun, 10 Sep 2023 09:19:28 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20221208 header.b=pv2iBpI0; spf=pass (domain: gmail.com, ip: 209.85.221.43, mailfrom: adrian.freihofer@gmail.com) Received: by mail-wr1-f43.google.com with SMTP id ffacd0b85a97d-31f7400cb74so2825717f8f.2 for ; Sun, 10 Sep 2023 09:19:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1694362766; x=1694967566; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=P1SnTuAhFxDpsGGX8wM7sKL+0XZkEv7Dw30w3L3RU5E=; b=pv2iBpI0E+HB07xQJ1kaLrr1dTQIwrF0hP+g9jhVi380E3Ew1Wn+7CdpPdXdUvOFmL cOPduJaoBLjTjjbgx/Zey87okvCmPNGzCYEl6H8mqhOWxzR7IolgGRWFGcvf9xphE14U 8klyXUac6kyRdTA7fPFEouvz087qAigYARabsbLBXQM8C6t6CEAxBANz/77gsh9FrOBL 6QtIwqyk49KPSHY/ugnoCz9xoHcB6gnn0s2D/McG1z5CwHlScj887V0b6rNcdBF2TPJh al2fhY9CXQ8oqWqMUe7xzhj4ycUnx5CEhO/9QkeIxEQ5j3I7M8SfFNsHmmQ0AQ2p7gtE bCgw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1694362766; x=1694967566; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=P1SnTuAhFxDpsGGX8wM7sKL+0XZkEv7Dw30w3L3RU5E=; b=WtcGF3KkTHKhACGdFHXvHX2lFLwGoWTaUzyXm0dg6O8oAZGoF/SWO5v+KqjHs3Uon8 dYLh8TIbeaj2T5NOA6SZses35q+Oii2aRtshqsTTFKkpfHtjZf6P7AW5/ozE6ulHf+6k z4lRnFkfhdtftnZe7etfr693zbCd3HdiVhlo1Zx9w/PrMeASlwC4KybbLkgMoCxmJvst vLYVZyh9cx6CO4c2ZrYG6NFUuIS9oHDT9eBigWlKtPfDrAzcujDYTdzgQal87O/BGiV8 w+VOGUs9Os/eN6t8Mronv8QJOXKacepW7IfVD5jdrfVoxtFNuMaH9/6Q20UK16fGeT+B Esjw== X-Gm-Message-State: AOJu0YzxM5L9jY92ESy359yNeIiqvtu+GCjnv4F0nwkiZk6z1ZT+eEV/ eHWK/0qJSqngP2bPdHkZotxvdZ5xCqs= X-Google-Smtp-Source: AGHT+IH8DQYF42lXJPFhhDco7hmkLN5Kizn9qOsX1ZSDsYPZs9t/7Z5oRPKMi3gIhOh4HMenf41s+Q== X-Received: by 2002:a5d:525a:0:b0:317:5f13:5c2f with SMTP id k26-20020a5d525a000000b003175f135c2fmr5813764wrc.0.1694362766379; Sun, 10 Sep 2023 09:19:26 -0700 (PDT) Received: from t14s-af.fritz.box ([2a02:169:59a6:0:dcf2:2f65:9442:83f]) by smtp.gmail.com with ESMTPSA id o12-20020a5d408c000000b003142ea7a661sm7605431wrp.21.2023.09.10.09.19.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 Sep 2023 09:19:25 -0700 (PDT) From: Adrian Freihofer X-Google-Original-From: Adrian Freihofer To: openembedded-core@lists.openembedded.org Cc: Adrian Freihofer Subject: [OE-core][PATCH v6 09/12] devtool: ide make deploy-target quicker Date: Sun, 10 Sep 2023 17:52:35 +0200 Message-ID: <20230910161850.4032227-10-adrian.freihofer@siemens.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230910161850.4032227-1-adrian.freihofer@siemens.com> References: <20230910161850.4032227-1-adrian.freihofer@siemens.com> MIME-Version: 1.0 List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Sun, 10 Sep 2023 16:19:29 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/187467 Instead of calling devtool deploy-target which starts a bitbake server to get some variables the previous refactoring allows to generate a simple script which does no longer depend on variables from bitbake. This is much faster. --- scripts/lib/devtool/ide.py | 115 ++++++++++++++++++------------------- 1 file changed, 55 insertions(+), 60 deletions(-) diff --git a/scripts/lib/devtool/ide.py b/scripts/lib/devtool/ide.py index 7c7040232c4..9c724509d48 100755 --- a/scripts/lib/devtool/ide.py +++ b/scripts/lib/devtool/ide.py @@ -9,6 +9,7 @@ import os import stat +import sys import logging import json import re @@ -360,15 +361,19 @@ class RecipeModified: self.bbappend = None # recipe variables from d.getVar self.b = None + self.base_libdir = None self.bpn = None self.d = None self.fakerootcmd = None self.fakerootenv = None + self.libdir = None + self.max_process = None self.package_arch = None self.path = None self.recipe_sysroot = None self.recipe_sysroot_native = None self.staging_incdir = None + self.strip_cmd = None self.target_arch = None self.workdir = None # replicate bitbake build environment @@ -387,11 +392,6 @@ class RecipeModified: self.meson_cross_file = None # vscode self.dot_code_dir = None - # TODO: remove calling devtool - self.bb_env_passthrough_additions = None - self.bbpath = None - self.bitbakepath = None - self.topdir = None def initialize(self, config, workspace, tinfoil): recipe_d = parse_recipe( @@ -413,10 +413,14 @@ class RecipeModified: shutil.rmtree(self.temp_dir) self.b = recipe_d.getVar('B') + self.base_libdir = recipe_d.getVar('base_libdir') self.bpn = recipe_d.getVar('BPN') self.d = recipe_d.getVar('D') self.fakerootcmd = recipe_d.getVar('FAKEROOTCMD') self.fakerootenv = recipe_d.getVar('FAKEROOTENV') + self.libdir = recipe_d.getVar('libdir'), + self.max_process = int(recipe_d.getVar( + "BB_NUMBER_THREADS") or os.cpu_count() or 1) self.package_arch = recipe_d.getVar('PACKAGE_ARCH') self.path = recipe_d.getVar('PATH') self.recipe_sysroot = os.path.realpath( @@ -425,15 +429,10 @@ class RecipeModified: recipe_d.getVar('RECIPE_SYSROOT_NATIVE')) self.staging_incdir = os.path.realpath( recipe_d.getVar('STAGING_INCDIR')) + self.strip_cmd = recipe_d.getVar('STRIP') self.target_arch = recipe_d.getVar('TARGET_ARCH') self.workdir = os.path.realpath(recipe_d.getVar('WORKDIR')) - self.bb_env_passthrough_additions = recipe_d.getVar( - 'BB_ENV_PASSTHROUGH_ADDITIONS') - self.bbpath = recipe_d.getVar('BBPATH') - self.bitbakepath = recipe_d.getVar('BITBAKEPATH') - self.topdir = recipe_d.getVar('TOPDIR') - self.__init_exported_variables(recipe_d) if bb.data.inherits_class('cmake', recipe_d): @@ -971,6 +970,38 @@ class RecipeModified: cmd_lines.append(install_cmd) return self.write_script(cmd_lines, 'bb_run_do_install') + def gen_deploy_target_script(self, args): + """Generate a quicker (works without tinfoil) variant of devtool target-deploy""" + cmd_lines = ['#!/usr/bin/env python3'] + cmd_lines.append('import sys') + cmd_lines.append('devtool_sys_path = %s' % str(sys.path)) + cmd_lines.append('devtool_sys_path.reverse()') + cmd_lines.append('for p in devtool_sys_path:') + cmd_lines.append(' if p not in sys.path:') + cmd_lines.append(' sys.path.insert(0, p)') + cmd_lines.append('from devtool.deploy import deploy_cached') + args_filter = ['debug', 'dry_run', 'key', 'no_check_space', 'no_host_check', + 'no_preserve', 'port', 'recipename', 'show_status', 'ssh_exec', 'strip', 'target'] + filtered_args_dict = {key: value for key, value in vars( + args).items() if key in args_filter} + cmd_lines.append('filtered_args_dict = %s' % str(filtered_args_dict)) + cmd_lines.append('class Dict2Class(object):') + cmd_lines.append(' def __init__(self, my_dict):') + cmd_lines.append(' for key in my_dict:') + cmd_lines.append(' setattr(self, key, my_dict[key])') + cmd_lines.append('filtered_args = Dict2Class(filtered_args_dict)') + cmd_lines.append('deploy_cached("%s", "%s", "%s", "%s", "%s", "%s", %d, "%s", "%s", filtered_args)' % + (self.d, self.workdir, self.path, self.strip_cmd, + self.libdir, self.base_libdir, self.max_process, + self.fakerootcmd, self.fakerootenv)) + return self.write_script(cmd_lines, 'deploy_target') + + def gen_install_deploy_script(self, args): + cmd_lines = ['#!/bin/sh'] + cmd_lines.append(self.gen_fakeroot_install_script()) + cmd_lines.append(self.gen_deploy_target_script(args)) + return self.write_script(cmd_lines, 'install_and_deploy') + def write_script(self, cmd_lines, script_name): bb.utils.mkdirhier(self.temp_dir) script_file = os.path.join(self.temp_dir, script_name) @@ -981,61 +1012,15 @@ class RecipeModified: return script_file def vscode_tasks(self, args, gdb_cross): - run_do_install = self.gen_fakeroot_install_script() - pythonpath_new = os.path.realpath( - os.path.join(self.bitbakepath, '../lib')) - try: - pythonpath = os.environ['PYTONPATH'].split(':') - if pythonpath_new not in pythonpath: - pythonpath = pythonpath_new + ":" + pythonpath - except KeyError: - pythonpath = pythonpath_new - install_label = "do_install %s" % self.bpn - deploy_label = "devtool deploy-target %s" % self.bpn - bb_env = { - # "BBPATH": self.bbpath, - "PYTHONPATH": pythonpath, - "BUILDDIR": self.topdir, - # Use e.g. Python from host, not python-native - "PATH": os.environ['PATH'], - "BB_ENV_PASSTHROUGH_ADDITIONS": self.bb_env_passthrough_additions - } - bb_options = { - "cwd": self.topdir - } + run_install_deploy = self.gen_install_deploy_script(args) tasks_dict = { "version": "2.0.0", "tasks": [ { - "label": install_label, - "type": "shell", - "command": run_do_install, - "problemMatcher": [] - }, - { - "label": deploy_label, + "label": "install && deploy-target %s" % self.bpn, "type": "shell", - "command": "devtool", # TODO: Generate a self contained script which does what devtool target-deploy does but without connection to the bitbake server - "args": ["--bbpath", self.bbpath, "deploy-target", self.bpn, args.target, "--strip", "--no-host-check"], - "linux": { - "options": { - "env": bb_env - }}, - "options": bb_options, + "command": run_install_deploy, "problemMatcher": [] - }, - { - "label": "install && deploy-target %s" % self.bpn, - "dependsOrder": "sequence", - "dependsOn": [ - install_label, - deploy_label - ], - "problemMatcher": [], - "group": { - "kind": "build", - "isDefault": True - } } ] } @@ -1183,6 +1168,16 @@ def register_commands(subparsers, context): '--skip-bitbake', help='Generate IDE configuration but skip calling bibtake to update the SDK.', action='store_true') parser_ide.add_argument( '-k', '--bitbake-k', help='Pass -k parameter to bitbake', action='store_true') + parser_ide.add_argument( + '--no-strip', help='Do not strip executables prior to deploy', dest='strip', action='store_false') + parser_ide.add_argument( + '-n', '--dry-run', help='List files to be undeployed only', action='store_true') + parser_ide.add_argument( + '-s', '--show-status', help='Show progress/status output', action='store_true') + parser_ide.add_argument( + '-p', '--no-preserve', help='Do not preserve existing files', action='store_true') + parser_ide.add_argument( + '--no-check-space', help='Do not check for available space before deploying', action='store_true') parser_ide.add_argument( '--debug-build-config', help='Use debug build flags, for example set CMAKE_BUILD_TYPE=Debug', action='store_true') parser_ide.set_defaults(func=ide_setup) From patchwork Sun Sep 10 15:52:36 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adrian Freihofer X-Patchwork-Id: 30259 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 E96E3EEB594 for ; Sun, 10 Sep 2023 16:19:29 +0000 (UTC) Received: from mail-wr1-f45.google.com (mail-wr1-f45.google.com [209.85.221.45]) by mx.groups.io with SMTP id smtpd.web10.39059.1694362769153463124 for ; Sun, 10 Sep 2023 09:19:29 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20221208 header.b=lehGL3O0; spf=pass (domain: gmail.com, ip: 209.85.221.45, mailfrom: adrian.freihofer@gmail.com) Received: by mail-wr1-f45.google.com with SMTP id ffacd0b85a97d-31f4a286ae1so3341079f8f.3 for ; Sun, 10 Sep 2023 09:19:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1694362767; x=1694967567; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Sv7+Ku4KF5JgOBQ3HF31jwDkk7kvG+2IIEvPIX8kbRU=; b=lehGL3O0KdF9Hytgjk2pSHVGXneHZktxwIGxCDjFogQMrtAPE3IdD24iAC87tCwnMg 1PLE5zW8qKj5LX7SnN+Wz4QILMERKUCitISFBCrVSp6+o02yl8h7h1jMTxTPOxSEF4/5 0g3GRxYHHcbX7vnlN1LEJkymSVs7QFDIvFk1kZHC/XRDbaLQtilT7f83PMqeFkfC+HPx gQj5PqgmG9tkuKZt94zsDVMiARkDZo1KGFIdsPkNbWZUt4SJXo1/XaLuFEh9htmPMTw5 RdOzIodgjnMvwi3H7azRrFDfcx/knRvYPT1rLN/+x7oMKy+I2DdQVt2bKrpLvWMgIBvg Ygrw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1694362767; x=1694967567; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Sv7+Ku4KF5JgOBQ3HF31jwDkk7kvG+2IIEvPIX8kbRU=; b=rMea7Z5y2cmvwNiKWl3++nDOSoQbq+jdwrVLnOmP5Nu5f2RJCvK4xiGjYP93v0h4oX zOhqcJa30ry1SCuF+wR54eGG6BMv3jeYk/KHhj6eWu+Md02tTy5JXax/oJF537Aj1js9 HmQOZ7meBg1XEQ2nv+mDMEDSRGAaArxKxqzahuzYUrPVcVoebOXgDG/bqjILrEoi0dA8 z08Zbc9ME74oNAcf1q4K0ncBp3wibVf9A5IR/s/NCqT4rgxZ9P9Dhcn4t0QhZxBZzzbA e2SMwbYz8aGcnSY6Yj9WggoKWqsVy+3q6fIffPwIRRAHRNEnyC0ids6N2dJislCc8OsB JVhA== X-Gm-Message-State: AOJu0Yw0e74wuub5Sx8i1YfOB4QiqT6Rl+RrWoMauM0WpYAa8t+JyV7L TrG+9mRPfDFiYLb4srbBj+HOOZZEM6k= X-Google-Smtp-Source: AGHT+IEXxaOAaqahLJsS8+X5V2EQM0enRL13Sn2lwZ9byX7VHsIN8rdlrfP160h2FDpJxSBNEThpeA== X-Received: by 2002:a5d:690d:0:b0:31c:6697:6947 with SMTP id t13-20020a5d690d000000b0031c66976947mr6248046wru.69.1694362767295; Sun, 10 Sep 2023 09:19:27 -0700 (PDT) Received: from t14s-af.fritz.box ([2a02:169:59a6:0:dcf2:2f65:9442:83f]) by smtp.gmail.com with ESMTPSA id o12-20020a5d408c000000b003142ea7a661sm7605431wrp.21.2023.09.10.09.19.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 Sep 2023 09:19:26 -0700 (PDT) From: Adrian Freihofer X-Google-Original-From: Adrian Freihofer To: openembedded-core@lists.openembedded.org Cc: Adrian Freihofer Subject: [OE-core][PATCH v6 10/12] oe-selftest devtool: refactor runqemu pre-requisites Date: Sun, 10 Sep 2023 17:52:36 +0200 Message-ID: <20230910161850.4032227-11-adrian.freihofer@siemens.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230910161850.4032227-1-adrian.freihofer@siemens.com> References: <20230910161850.4032227-1-adrian.freihofer@siemens.com> MIME-Version: 1.0 List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Sun, 10 Sep 2023 16:19:29 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/187468 Split runqemu pre-requisites into a function which can be re-used by other tests as well. Signed-off-by: Adrian Freihofer --- meta/lib/oeqa/selftest/cases/devtool.py | 48 +++++++++++++------------ 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/meta/lib/oeqa/selftest/cases/devtool.py b/meta/lib/oeqa/selftest/cases/devtool.py index a2b77e528de..b577f6d62a1 100644 --- a/meta/lib/oeqa/selftest/cases/devtool.py +++ b/meta/lib/oeqa/selftest/cases/devtool.py @@ -256,6 +256,31 @@ class DevtoolTestCase(OESelftestTestCase): if remaining_removelines: self.fail('Expected removed lines not found: %s' % remaining_removelines) + def _check_runqemu_prerequisites(self): + """Check runqemu is available + + Whilst some tests would seemingly be better placed as a runtime test, + unfortunately the runtime tests run under bitbake and you can't run + devtool within bitbake (since devtool needs to run bitbake itself). + Additionally we are testing build-time functionality as well, so + really this has to be done as an oe-selftest test. + """ + machine = get_bb_var('MACHINE') + if not machine.startswith('qemu'): + self.skipTest('This test only works with qemu machines') + if not os.path.exists('/etc/runqemu-nosudo'): + self.skipTest('You must set up tap devices with scripts/runqemu-gen-tapdevs before running this test') + result = runCmd('PATH="$PATH:/sbin:/usr/sbin" ip tuntap show', ignore_status=True) + if result.status != 0: + result = runCmd('PATH="$PATH:/sbin:/usr/sbin" ifconfig -a', ignore_status=True) + if result.status != 0: + self.skipTest('Failed to determine if tap devices exist with ifconfig or ip: %s' % result.output) + for line in result.output.splitlines(): + if line.startswith('tap'): + break + else: + self.skipTest('No tap devices found - you must set up tap devices with scripts/runqemu-gen-tapdevs before running this test') + def _test_devtool_add_git_url(self, git_url, version, pn, resulting_src_uri): self.track_for_cleanup(self.workspacedir) self.add_command_to_tearDown('bitbake-layers remove-layer */workspace') @@ -1616,28 +1641,7 @@ class DevtoolExtractTests(DevtoolBase): @OETestTag("runqemu") def test_devtool_deploy_target(self): - # NOTE: Whilst this test would seemingly be better placed as a runtime test, - # unfortunately the runtime tests run under bitbake and you can't run - # devtool within bitbake (since devtool needs to run bitbake itself). - # Additionally we are testing build-time functionality as well, so - # really this has to be done as an oe-selftest test. - # - # Check preconditions - machine = get_bb_var('MACHINE') - if not machine.startswith('qemu'): - self.skipTest('This test only works with qemu machines') - if not os.path.exists('/etc/runqemu-nosudo'): - self.skipTest('You must set up tap devices with scripts/runqemu-gen-tapdevs before running this test') - result = runCmd('PATH="$PATH:/sbin:/usr/sbin" ip tuntap show', ignore_status=True) - if result.status != 0: - result = runCmd('PATH="$PATH:/sbin:/usr/sbin" ifconfig -a', ignore_status=True) - if result.status != 0: - self.skipTest('Failed to determine if tap devices exist with ifconfig or ip: %s' % result.output) - for line in result.output.splitlines(): - if line.startswith('tap'): - break - else: - self.skipTest('No tap devices found - you must set up tap devices with scripts/runqemu-gen-tapdevs before running this test') + self._check_runqemu_prerequisites() self.assertTrue(not os.path.exists(self.workspacedir), 'This test cannot be run with a workspace directory under the build directory') # Definitions testrecipe = 'mdadm' From patchwork Sun Sep 10 15:52:37 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adrian Freihofer X-Patchwork-Id: 30263 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 E4DB5EE49A4 for ; Sun, 10 Sep 2023 16:19:39 +0000 (UTC) Received: from mail-wr1-f52.google.com (mail-wr1-f52.google.com [209.85.221.52]) by mx.groups.io with SMTP id smtpd.web11.39128.1694362770033274548 for ; Sun, 10 Sep 2023 09:19:30 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20221208 header.b=ehn2yqww; spf=pass (domain: gmail.com, ip: 209.85.221.52, mailfrom: adrian.freihofer@gmail.com) Received: by mail-wr1-f52.google.com with SMTP id ffacd0b85a97d-31c4d5bd69cso3781272f8f.3 for ; Sun, 10 Sep 2023 09:19:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1694362768; x=1694967568; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=wk/OdDDRABIV0HrxQ+Ir4uIVgRSXUf8pgoJihVXB03o=; b=ehn2yqwwf4Oz6i0w5S6GhDsGo6sK1x7jP1G4umVI2h3nQuHc2B4ECLsmUdERXmK7bd CeaHeF63yYlUf5qTIoeLeGUCqj4l65ih+z+J1BXT3I4z+FADncmfMYVXr3YK6bU6vGUY VMJfklTh6wMLPVsuyp6XkWQkzBixLib2zgd4o1qoqfHjMfIJZUSECiCDJLbVFIUh5Doc bNl29G1gKfEEa9cNlOrtJE2mmIt5o/7bVevklEVC4igZ6dLweGkulSjUPRnfrAchRd+0 8KmdxY3E7BZQmmTTizp3YHOnHwSlKUizVLndCl3x9NLZLKJI5xhtlHg5ZqjyMUREX8ej yOmQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1694362768; x=1694967568; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=wk/OdDDRABIV0HrxQ+Ir4uIVgRSXUf8pgoJihVXB03o=; b=hwixCp1k3MeMhrvvw0EYC1FGR0BN+JI62LJ/I/RTTd/MphBGL1dyqvjPRgqO186RnT NmBwLvXYtb3eKMB2/fHZloObpfxHnR0YM2b5/4SvhkFAL17ON4TpukaVMWjMV/BK65Fm l/5G/qm6AOQpaTVkJmMIOaV+ZKkX4xLF9p+pCD0uFzUvk+M9ycFX8GVZB5I/MzI3WeYW H1zaXRzL75lenvSpOOxv9u/p0/w+7vojifoRzK70zGvGUz3JxlbOW3ToNLMrZoGMQXI9 r9rtOMxK8EaD/F/PpfkRAvaZd3svLpeDeZqW0JlQ9vgfUZZIVTXVIs5xijK8wj+bskeU vcVg== X-Gm-Message-State: AOJu0YwvItEigg1Qu1bL+xsu6si4S/8kTuYP0yeb24l5WSwtCB3XH8D5 cUE8BzNDG9OFdhR4SoTrQJZ5Vvt6oak= X-Google-Smtp-Source: AGHT+IFMcwtK7h/bRJxusA/rXPcaBREQgjuXJ9kw7Cfw3038kMCpuxISsQ9YSqY3RS4hccDGLMbBHA== X-Received: by 2002:adf:d082:0:b0:31d:c3d2:4300 with SMTP id y2-20020adfd082000000b0031dc3d24300mr5055806wrh.71.1694362768104; Sun, 10 Sep 2023 09:19:28 -0700 (PDT) Received: from t14s-af.fritz.box ([2a02:169:59a6:0:dcf2:2f65:9442:83f]) by smtp.gmail.com with ESMTPSA id o12-20020a5d408c000000b003142ea7a661sm7605431wrp.21.2023.09.10.09.19.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 Sep 2023 09:19:27 -0700 (PDT) From: Adrian Freihofer X-Google-Original-From: Adrian Freihofer To: openembedded-core@lists.openembedded.org Cc: Adrian Freihofer Subject: [OE-core][PATCH v6 11/12] oe-selftest devtool: ide tests Date: Sun, 10 Sep 2023 17:52:37 +0200 Message-ID: <20230910161850.4032227-12-adrian.freihofer@siemens.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230910161850.4032227-1-adrian.freihofer@siemens.com> References: <20230910161850.4032227-1-adrian.freihofer@siemens.com> MIME-Version: 1.0 List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Sun, 10 Sep 2023 16:19:39 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/187469 Signed-off-by: Adrian Freihofer --- meta/lib/oeqa/selftest/cases/devtool.py | 179 ++++++++++++++++++++++++ 1 file changed, 179 insertions(+) diff --git a/meta/lib/oeqa/selftest/cases/devtool.py b/meta/lib/oeqa/selftest/cases/devtool.py index b577f6d62a1..158e016b895 100644 --- a/meta/lib/oeqa/selftest/cases/devtool.py +++ b/meta/lib/oeqa/selftest/cases/devtool.py @@ -11,6 +11,7 @@ import tempfile import glob import fnmatch import unittest +import json from oeqa.selftest.case import OESelftestTestCase from oeqa.utils.commands import runCmd, bitbake, get_bb_var, create_temp_layer @@ -2196,3 +2197,181 @@ class DevtoolUpgradeTests(DevtoolBase): #Step 4.5 runCmd("grep %s %s" % (modconfopt, codeconfigfile)) + + + +class DevtoolIdeTests(DevtoolBase): + def __devtool_ide_recipe(self, recipe_name, build_file, testimage): + self._check_runqemu_prerequisites() + tempdir = tempfile.mkdtemp(prefix='devtoolqa') + self.track_for_cleanup(tempdir) + self.track_for_cleanup(self.workspacedir) + self.add_command_to_tearDown('bitbake -c clean %s' % recipe_name) + self.add_command_to_tearDown('bitbake-layers remove-layer */workspace') + + conf_lines = [ + 'IMAGE_CLASSES += "image-combined-dbg"', + 'IMAGE_GEN_DEBUGFS = "1"', + 'IMAGE_INSTALL:append = " gdbserver %s-ptest"' % recipe_name + ] + self.write_config("\n".join(conf_lines)) + + result = runCmd('devtool modify %s -x %s' % (recipe_name, tempdir)) + self.assertExists(os.path.join(tempdir, build_file), + 'Extracted source could not be found') + self.assertExists(os.path.join(self.workspacedir, 'conf', + 'layer.conf'), 'Workspace directory not created') + matches = glob.glob(os.path.join(self.workspacedir, + 'appends', recipe_name + '.bbappend')) + self.assertTrue(matches, 'bbappend not created %s' % result.output) + + # Test devtool status + result = runCmd('devtool status') + self.assertIn(recipe_name, result.output) + self.assertIn(tempdir, result.output) + self._check_src_repo(tempdir) + + # Usually devtool ide would initiate the build of the SDK. + # But there is a circular dependency with starting Qemu and passing the IP of runqemu to devtool ide. + bitbake("%s qemu-native qemu-helper-native" % testimage) + deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE') + self.add_command_to_tearDown('bitbake -c clean %s' % testimage) + self.add_command_to_tearDown('rm -f %s/%s*' % (deploy_dir_image, testimage)) + + return tempdir + + def __devtool_ide_qemu(self, tempdir, qemu, recipe_name, bitbake_sdk_cmd, example_exe): + # Verify do_install works + with open(os.path.join(tempdir, '.vscode', 'tasks.json')) as tasks_j: + tasks_d = json.load(tasks_j) + tasks = tasks_d["tasks"] + task_install = next((task for task in tasks if task["label"] == "install && deploy-target %s" % recipe_name), None) + self.assertIsNot(task_install, None) + install_deploy_cmd = task_install["command"] + # execute only the bb_run_do_install script since the deploy would require e.g. Qemu running. + install_cmd = install_deploy_cmd.replace("install_and_deploy", "bb_run_do_install") + runCmd(install_cmd, cwd=tempdir) + + # Verify if re-building the SDK still works and the deploy and install script gets generated + runCmd(bitbake_sdk_cmd) + self.assertExists(install_deploy_cmd, 'install_and_deploy script not found') + + MAGIC_STRING_ORIG = "Magic: 123456789" + MAGIC_STRING_NEW = "Magic: 987654321" + ptest_cmd = "ptest-runner " + recipe_name + + # Verify the unmodified example prints the magic string + status, output = qemu.run(example_exe) + self.assertEqual(status, 0, msg="%s failed: %s" % (example_exe, output)) + self.assertIn(MAGIC_STRING_ORIG, output) + + # Verify the unmodified ptests work + status, output = qemu.run(ptest_cmd) + self.assertEqual(status, 0, msg="%s failed: %s" % (ptest_cmd, output)) + self.assertIn("PASS: cpp-example-lib", output) + + # Replace the Magic String in the code, compile and deploy to Qemu + cpp_example_lib_hpp = os.path.join(tempdir, 'cpp-example-lib.hpp') + with open(cpp_example_lib_hpp, 'r') as file: + cpp_code = file.read() + cpp_code = cpp_code.replace(MAGIC_STRING_ORIG, MAGIC_STRING_NEW) + with open(cpp_example_lib_hpp, 'w') as file: + file.write(cpp_code) + runCmd(install_deploy_cmd, cwd=tempdir) + + # Verify the modified example prints the modified magic string + status, output = qemu.run(example_exe) + self.assertEqual(status, 0, msg="%s failed: %s" % (example_exe, output)) + self.assertNotIn(MAGIC_STRING_ORIG, output) + self.assertIn(MAGIC_STRING_NEW, output) + + # Verify the modified example ptests work + status, output = qemu.run(ptest_cmd) + self.assertEqual(status, 0, msg="%s failed: %s" % (ptest_cmd, output)) + self.assertIn("PASS: cpp-example-lib", output) + + @OETestTag("runqemu") + def test_devtool_ide_recipe_cmake(self): + recipe_name = "cmake-example" + example_exe = "cmake-example" + build_file = "CMakeLists.txt" + testimage = "oe-selftest-image" + + tempdir = self.__devtool_ide_recipe(recipe_name, build_file, testimage) + + # Verify deployment to Qemu works + with runqemu(testimage) as qemu: + bitbake_sdk_cmd = 'devtool ide %s %s -t root@%s -c --ide=code' % (recipe_name, testimage, qemu.ip) + runCmd(bitbake_sdk_cmd) + + with open(os.path.join(tempdir, 'CMakeUserPresets.json')) as cmake_preset_j: + cmake_preset_d = json.load(cmake_preset_j) + config_presets = cmake_preset_d["configurePresets"] + self.assertEqual(len(config_presets), 1) + cmake_exe = config_presets[0]["cmakeExecutable"] + preset_name = config_presets[0]["name"] + + # Verify the wrapper for cmake native is available + self.assertExists(cmake_exe) + + # Verify the cmake preset generated by devtool ide is available + result = runCmd('%s --list-presets' % cmake_exe, cwd=tempdir) + self.assertIn(preset_name, result.output) + + # Verify cmake re-uses the o files compiled by bitbake + result = runCmd('%s --build --preset %s' % (cmake_exe, preset_name), cwd=tempdir) + self.assertIn("ninja: no work to do.", result.output) + + # Verify the unit tests work (in Qemu) + result = runCmd('%s --build --preset %s --target test' % (cmake_exe, preset_name), cwd=tempdir) + self.assertIn("100% tests passed", result.output) + + # Verify re-building and testing works again + result = runCmd('%s --build --preset %s --target clean' % (cmake_exe, preset_name), cwd=tempdir) + self.assertIn("Cleaning all built files...", result.output) + result = runCmd('%s --build --preset %s' % (cmake_exe, preset_name), cwd=tempdir) + self.assertIn("Building", result.output) + self.assertIn("Linking", result.output) + result = runCmd('%s --build --preset %s --target test' % (cmake_exe, preset_name), cwd=tempdir) + self.assertIn("Running tests...", result.output) + self.assertIn("100% tests passed", result.output) + + self.__devtool_ide_qemu(tempdir, qemu, recipe_name, bitbake_sdk_cmd, example_exe) + + @OETestTag("runqemu") + def test_devtool_ide_recipe_meson(self): + recipe_name = "meson-example" + example_exe = "mesonex" + build_file = "meson.build" + testimage = "oe-selftest-image" + + tempdir = self.__devtool_ide_recipe(recipe_name, build_file, testimage) + + # Verify deployment to Qemu works + with runqemu(testimage) as qemu: + bitbake_sdk_cmd = 'devtool ide %s %s -t root@%s -c --ide=code' % (recipe_name, testimage, qemu.ip) + runCmd(bitbake_sdk_cmd) + + with open(os.path.join(tempdir, '.vscode', 'settings.json')) as settings_j: + settings_d = json.load(settings_j) + meson_exe = settings_d["mesonbuild.mesonPath"] + meson_build_folder = settings_d["mesonbuild.buildFolder"] + + # Verify the wrapper for meson native is available + self.assertExists(meson_exe) + + # Verify meson re-uses the o files compiled by bitbake + result = runCmd('%s compile -C %s' % (meson_exe, meson_build_folder), cwd=tempdir) + self.assertIn("ninja: no work to do.", result.output) + + # Verify the unit tests work (in Qemu) + runCmd('%s test -C %s' % (meson_exe, meson_build_folder), cwd=tempdir) + + # Verify re-building and testing works again + result = runCmd('%s compile -C %s --clean' % (meson_exe, meson_build_folder), cwd=tempdir) + self.assertIn("Cleaning...", result.output) + result = runCmd('%s compile -C %s' % (meson_exe, meson_build_folder), cwd=tempdir) + self.assertIn("Linking target %s" % example_exe, result.output) + runCmd('%s test -C %s' % (meson_exe, meson_build_folder), cwd=tempdir) + + self.__devtool_ide_qemu(tempdir, qemu, recipe_name, bitbake_sdk_cmd, example_exe) From patchwork Sun Sep 10 15:52:38 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adrian Freihofer X-Patchwork-Id: 30262 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 E4DF1EEB57D for ; Sun, 10 Sep 2023 16:19:39 +0000 (UTC) Received: from mail-wr1-f48.google.com (mail-wr1-f48.google.com [209.85.221.48]) by mx.groups.io with SMTP id smtpd.web11.39130.1694362770777027885 for ; Sun, 10 Sep 2023 09:19:31 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20221208 header.b=d/vsVVDy; spf=pass (domain: gmail.com, ip: 209.85.221.48, mailfrom: adrian.freihofer@gmail.com) Received: by mail-wr1-f48.google.com with SMTP id ffacd0b85a97d-307d20548adso3652194f8f.0 for ; Sun, 10 Sep 2023 09:19:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1694362769; x=1694967569; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=AoenDSfxEhrJSXJzwNF0qUZi4ZdzROlnUR735GqJdd4=; b=d/vsVVDy/2ZK5pcyH7VapqQGMuiKyPnooEzkdH4/FyZC37fFLgBdQyLtbduVsrDpfo 1gfe4Tn1F9yfwwZck9kibtzcwQJigsIZbhR9V7Sv/WbJQzGhU2Zsjf1KxhKR9VzGeP+w gHStm5xS+cETbuOA+KsuhKaCKwK7CYvIB5mBy7OjopwQKobUHrEjcTpgf5ZPPs+0nEUo wpDNY7Urvi+HvovbP/8FuOvG2yQERVPxaJTB4mnIqGGXkc1ULfcddhOkSXbC1zst8rwX bKu2vPHWK88+o4Lsjv5gwmZpdnkwi/7Ph/mb+eajxVPwImXadFApB3Law9uoQFncVvzb VhKg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1694362769; x=1694967569; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=AoenDSfxEhrJSXJzwNF0qUZi4ZdzROlnUR735GqJdd4=; b=Auf4jUP8RQH6kd/LNQBL/fY+VIrn9r/vgdnm4ZtA3M0jceapF8/1JX+L6Kg3fEpFJK ThXpONNpGUS1Lh2uCbwlYVzlGmZaEuqhMgZtRvHQGgDqXf+LsIZ76LKbtD3morPCy6Ee gVeDpr+nQkkuIMqEB5tBAUjnmI1PnokZbpj2AJV0ehjBRwjL036eVGbkzxsAfFB4vuI+ Lbuj1ba2LYG3qZvDplaDYz7Yc3kmDGSHiuUm4/BauYP2b+UMS3dFvayKmbJMK7sHP/z0 PcS8CjTsXSiaJAWVeuo7pqSWDbAyL/GDfNJw13exb747/bhMTC3TVMt9PAfEXotAMJJv nLAA== X-Gm-Message-State: AOJu0Yytn1eIqhOLySTU1zM7+ABAX0uqdnK3ZZ/KSYZl6jAj9mXM0S0v Sq8eRlPWLBmu3mKgwRlDkjk8UzDJ2fc= X-Google-Smtp-Source: AGHT+IHFscbUoyp36emfChJc3KPojtVFJmRmigXqV1Dx3Oi+AYMToAOs5wbQvOWWzeoKdAYITquMHA== X-Received: by 2002:adf:f74e:0:b0:319:83e8:fccf with SMTP id z14-20020adff74e000000b0031983e8fccfmr5811276wrp.23.1694362768990; Sun, 10 Sep 2023 09:19:28 -0700 (PDT) Received: from t14s-af.fritz.box ([2a02:169:59a6:0:dcf2:2f65:9442:83f]) by smtp.gmail.com with ESMTPSA id o12-20020a5d408c000000b003142ea7a661sm7605431wrp.21.2023.09.10.09.19.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 Sep 2023 09:19:28 -0700 (PDT) From: Adrian Freihofer X-Google-Original-From: Adrian Freihofer To: openembedded-core@lists.openembedded.org Cc: Adrian Freihofer Subject: [OE-core][PATCH v6 12/12] docs: cover devtool ide Date: Sun, 10 Sep 2023 17:52:38 +0200 Message-ID: <20230910161850.4032227-13-adrian.freihofer@siemens.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230910161850.4032227-1-adrian.freihofer@siemens.com> References: <20230910161850.4032227-1-adrian.freihofer@siemens.com> MIME-Version: 1.0 List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Sun, 10 Sep 2023 16:19:39 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/187470 Signed-off-by: Adrian Freihofer --- documentation/sdk-manual/extensible.rst | 97 ++++++++++++++++++++++++- 1 file changed, 96 insertions(+), 1 deletion(-) diff --git a/documentation/sdk-manual/extensible.rst b/documentation/sdk-manual/extensible.rst index 9e08e57a4e7..d05d4e36aa7 100644 --- a/documentation/sdk-manual/extensible.rst +++ b/documentation/sdk-manual/extensible.rst @@ -237,7 +237,7 @@ all the commands. devtool quick reference. -Three ``devtool`` subcommands provide entry-points into +Four ``devtool`` subcommands provide entry-points into development: - *devtool add*: Assists in adding new software to be built. @@ -245,6 +245,8 @@ development: - *devtool modify*: Sets up an environment to enable you to modify the source of an existing component. +- *devtool ide*: Generates a configuration for an IDE. + - *devtool upgrade*: Updates an existing recipe so that you can build it for an updated set of source files. @@ -632,6 +634,99 @@ command: proceed with your work. If you do use this command, realize that the source tree is preserved. +Use ``devtool ide`` to generate an configuration for the IDE +------------------------------------------------------------ + +``devtool ide`` automatically configures the IDE for cross-compiling and remote debugging. +The IDE is configured to call for example cmake directly. This has several advantages. +First of all it is much faster than using e.g. ``devtool build``. But it also allows to +use the very good integration of build tools like cmake or gdb with VSCode directly. + +Two different use cases are supported: + +- Generate the IDE configuration for a workspace created by ``devtool modify``. + +- Generate the IDE configuration for using a cross-toolchain as provided by + ``bitbake meta-ide-support build-sysroots``. + +Assuming the development environment is set up correctly and a workspace has been created +for the recipe using ``devtool modify recipe``, the following command can create the +configuration for VSCode in the recipe workspace: + + $ devtool ide recipe core-image-minimal --target root@192.168.7.2 + +What this command does exactly depends on the recipe or the build tool used by the recipe. +Currently, only CMake and Meson are supported natively. + +For a recipe which inherits cmake it does: + +- Prepare the SDK by calling bitbake core-image-minimal, gdb-cross, qemu-native... + +- Generate a cmake-preset with configures cmake to use exactly the same environent and + the same cmake-cache configuration as used by ``bitbake recipe``. The cmake-preset referres + to the per-recipe-sysroot of the recipe. + + Currently Configure, Build and Test presets are supported. Test presets execute the test + binaries with Qemu. + +- Generates a helper script to handle the do_install with pseudo + +- Generates some helper scripts to start the gdbserver on the target device + +- Generates the ``.vscode`` folder containing the following files: + + - c_ccp_properties.json: configure the code navigation + + - extensions.json: Recommend the extensions which are used. + + - launch.json: Provide a configuration for remote debugging with gdb-cross and gdbserver. + The debug-symbols are searched in the build-folder, the per-recipe-sysroot and the rootfs-dbg + folder which is provided by the image. + + - settings.json: confgure the indexer to ignore the build folders + + - tasks.json: Provide some helpers for running + + - do_install and ``devtool deploy-target`` + + - start the gdbserver via ssh + +For a recipe which inherits meson a similar configuration is generated. +Because there is nothing like a meson-preset a wrapper script for meson is generated. + +For some special recipes and use cases a per-recipe-sysroot based SDK is not suitable. +Therefore devtool ide also supports setting up the shared sysroots environment and generating +a IDE configurations referring to the shared sysroots. Recipes leading to a shared sysroot +are for example meta-ide-support or shared-sysroots. Also passing none as a recipe name leads +to a shared sysroot SDK. + + $ devtool ide none core-image-minimal + +In case of a shared sysroot SDK the configuration which gets generated for VSCode exposes the +cross-tool-chain as a cmake-kit. If a cmake project is loaded into VSCode the cross-toolchain +can be selected for compiling. + +The default IDE is VSCode. Some hints about using VSCode: + +- To work with cmake press ``Ctrl + Shift + p``, type cmake. + This will show some possible commands like selecting a cmake preset, compiling or running ctest. + A cmake kit might be activated by ``Ctrl + Shift + p``, type cmake quick start, + if not preset file is in the wokspace. + +- To work with meson press ``Ctrl + Shift + p``, type meson. + This will show some possible commands like compiling or executing the unit tests. + +- For the deployment to the target device, just press ``Ctrl + Shift + p``, type task. + Select the install & deploy task. + +- For remote debugging, switch to the debugging view by pressing the play button with the bug on the left side. + This will provide a green play button with a drop-down list where a debug configuration can be selected. + After selecting one of the generated configurations, press the play button. + +Additionally ``--ide=none`` is supported. +With the none IDE some generic configurations files like .gdbinit files and some helper scripts +are generated. + Use ``devtool upgrade`` to Create a Version of the Recipe that Supports a Newer Version of the Software -------------------------------------------------------------------------------------------------------