From patchwork Sun Oct 11 20:34:59 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 271549 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 735DAC433E7 for ; Sun, 11 Oct 2020 20:37:40 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id B476F20756 for ; Sun, 11 Oct 2020 20:37:39 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="FkQJBNEE" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org B476F20756 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:51496 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kRi66-0001p5-ER for qemu-devel@archiver.kernel.org; Sun, 11 Oct 2020 16:37:38 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:57322) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kRi4B-0008WK-50 for qemu-devel@nongnu.org; Sun, 11 Oct 2020 16:35:39 -0400 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:47529) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1kRi49-0005Qy-K7 for qemu-devel@nongnu.org; Sun, 11 Oct 2020 16:35:38 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1602448536; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=DRDoZioQbQ1N48Nel/LGXnmQnrp9I+d1CojiZL58o3E=; b=FkQJBNEEMXGC47VajIGf+3AJkBYnEE5QAefxtgwatP3LEVogrFL9WjCWDv3R+DiXGOfWnM 7tnIoCBXa01ZiAQ0IZLL1ErPBIJHQeBps+xojrnpDdNnoJXT+RVGZsJNmbXJ3PC+ROEUZM b/QZy1qAl80IgulKnuAAYi5I0CHDuRs= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-497-FuKsiZDeMPSY5uutpIVV4w-1; Sun, 11 Oct 2020 16:35:35 -0400 X-MC-Unique: FuKsiZDeMPSY5uutpIVV4w-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 1A6E6802B4A for ; Sun, 11 Oct 2020 20:35:34 +0000 (UTC) Received: from localhost (unknown [10.36.110.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id D0CBB100239A; Sun, 11 Oct 2020 20:35:27 +0000 (UTC) From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Subject: [PoCv2 01/15] mingw: fix error __USE_MINGW_ANSI_STDIO redefined Date: Mon, 12 Oct 2020 00:34:59 +0400 Message-Id: <20201011203513.1621355-2-marcandre.lureau@redhat.com> In-Reply-To: <20201011203513.1621355-1-marcandre.lureau@redhat.com> References: <20201011203513.1621355-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=marcandre.lureau@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=216.205.24.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/10/11 16:35:36 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=-0.01, RCVD_IN_MSPIKE_WL=-0.01, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: pbonzini@redhat.com, berrange@redhat.com, armbru@redhat.com, stefanha@redhat.com, =?utf-8?q?Marc-Andr=C3=A9_Lureau?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Marc-André Lureau Always put osdep.h first, and remove redundant stdlib.h include. Signed-off-by: Marc-André Lureau --- migration/dirtyrate.c | 3 ++- tests/test-bitmap.c | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/migration/dirtyrate.c b/migration/dirtyrate.c index 68577ef250..47f761e67a 100644 --- a/migration/dirtyrate.c +++ b/migration/dirtyrate.c @@ -10,8 +10,9 @@ * See the COPYING file in the top-level directory. */ -#include #include "qemu/osdep.h" + +#include #include "qapi/error.h" #include "cpu.h" #include "qemu/config-file.h" diff --git a/tests/test-bitmap.c b/tests/test-bitmap.c index 2f5b71458a..8db4f67883 100644 --- a/tests/test-bitmap.c +++ b/tests/test-bitmap.c @@ -8,7 +8,6 @@ * Author: Peter Xu */ -#include #include "qemu/osdep.h" #include "qemu/bitmap.h" From patchwork Sun Oct 11 20:35:00 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 271548 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.5 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6E1B6C433E7 for ; Sun, 11 Oct 2020 20:37:44 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id F0D6820756 for ; Sun, 11 Oct 2020 20:37:43 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="NDGotNuN" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org F0D6820756 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:51922 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kRi6A-00022E-Ty for qemu-devel@archiver.kernel.org; Sun, 11 Oct 2020 16:37:42 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:57338) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kRi4N-0000FD-JS for qemu-devel@nongnu.org; Sun, 11 Oct 2020 16:35:51 -0400 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:54911) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1kRi4L-0005RK-JY for qemu-devel@nongnu.org; Sun, 11 Oct 2020 16:35:51 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1602448548; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=YLHeBMskUZtqp132SdnBx+YQ+oQMCEZflKukbUd3w2w=; b=NDGotNuN3dOAS9G9KcUr6veFjB1UtcbuLk6fwOvkupILsz6a6PJTUaSdiBLzYP/VGEU4uE CyDU/7NXgQDSRPv3lzC1cFahH5DqP6wMXAjYAN+ts7OQfr/dys9oaAou101V2ZwyVSPrw3 EusGPmOv8M+6Ba8lplSkMl8ICg1XT78= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-111-VGHrBFH8ORGgjotoD5yijQ-1; Sun, 11 Oct 2020 16:35:46 -0400 X-MC-Unique: VGHrBFH8ORGgjotoD5yijQ-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 5AEB3107ACF5 for ; Sun, 11 Oct 2020 20:35:45 +0000 (UTC) Received: from localhost (unknown [10.36.110.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id 7AD2060C05; Sun, 11 Oct 2020 20:35:38 +0000 (UTC) From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Subject: [PoCv2 02/15] scripts/qapi: teach c_param_type() to return const argument type Date: Mon, 12 Oct 2020 00:35:00 +0400 Message-Id: <20201011203513.1621355-3-marcandre.lureau@redhat.com> In-Reply-To: <20201011203513.1621355-1-marcandre.lureau@redhat.com> References: <20201011203513.1621355-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=marcandre.lureau@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=216.205.24.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/10/11 16:35:36 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=-0.01, RCVD_IN_MSPIKE_WL=-0.01, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: pbonzini@redhat.com, berrange@redhat.com, armbru@redhat.com, stefanha@redhat.com, =?utf-8?q?Marc-Andr=C3=A9_Lureau?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Marc-André Lureau As it should be, since the argument isn't owned by the callee, but a lot of code in QEMU rely on non-const arguments to tweak it. Since Rust types / bindings are derived from the C version, we have to be more accurate there to do correct ownership conversions. Signed-off-by: Marc-André Lureau --- scripts/qapi/schema.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/scripts/qapi/schema.py b/scripts/qapi/schema.py index d1307ec661..ca85c7273a 100644 --- a/scripts/qapi/schema.py +++ b/scripts/qapi/schema.py @@ -167,8 +167,14 @@ class QAPISchemaType(QAPISchemaEntity): pass # Return the C type to be used in a parameter list. - def c_param_type(self): - return self.c_type() + # + # The argument should be considered const, since no ownership is given to the callee, + # but qemu C code frequently tweaks it. Set const=True for a stricter declaration. + def c_param_type(self, const=False): + c_type = self.c_type() + if const and c_type.endswith(pointer_suffix): + c_type = 'const ' + c_type + return c_type # Return the C type to be used where we suppress boxing. def c_unboxed_type(self): @@ -221,10 +227,10 @@ class QAPISchemaBuiltinType(QAPISchemaType): def c_type(self): return self._c_type_name - def c_param_type(self): + def c_param_type(self, const=False): if self.name == 'str': return 'const ' + self._c_type_name - return self._c_type_name + return super().c_param_type(const) def json_type(self): return self._json_type_name From patchwork Sun Oct 11 20:35:01 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 303143 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.5 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 17F1EC433DF for ; Sun, 11 Oct 2020 20:38:50 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 9F8EA207FB for ; Sun, 11 Oct 2020 20:38:49 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="AwnaOIPf" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 9F8EA207FB Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:58028 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kRi7E-0004b1-HI for qemu-devel@archiver.kernel.org; Sun, 11 Oct 2020 16:38:48 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:57352) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kRi4a-0000bj-1o for qemu-devel@nongnu.org; Sun, 11 Oct 2020 16:36:04 -0400 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:32527) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1kRi4V-0005Rh-T1 for qemu-devel@nongnu.org; Sun, 11 Oct 2020 16:36:03 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1602448559; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=g62JLdVzZ+lYru1vuaaHc3s3y6QR6Xc2NvMfJYPMMUA=; b=AwnaOIPfcLMBbnv2hUjlhT1PNBLhsuVHE6ttkqg8FIj+qAFF1zyS93uUrmRbSvW+ZWtYMO dS4i8T77ZocrEi1VNoCLotUAWvTPvMWap1KvXnSKWLQTm2aGqDMCVDivVTmox4LNWTK1PN ByBFcHIuje+u4auwK7fMVgBnFO+LIUo= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-305-ZysuvIkDNPivcUzTFJ8Owg-1; Sun, 11 Oct 2020 16:35:56 -0400 X-MC-Unique: ZysuvIkDNPivcUzTFJ8Owg-1 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 9ACA52FD01 for ; Sun, 11 Oct 2020 20:35:55 +0000 (UTC) Received: from localhost (unknown [10.36.110.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2FC155DA30; Sun, 11 Oct 2020 20:35:48 +0000 (UTC) From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Subject: [PoCv2 03/15] build-sys: add --with-rust{-target} & basic build infrastructure Date: Mon, 12 Oct 2020 00:35:01 +0400 Message-Id: <20201011203513.1621355-4-marcandre.lureau@redhat.com> In-Reply-To: <20201011203513.1621355-1-marcandre.lureau@redhat.com> References: <20201011203513.1621355-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=marcandre.lureau@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=216.205.24.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/10/11 16:35:36 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=-0.01, RCVD_IN_MSPIKE_WL=-0.01, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: pbonzini@redhat.com, berrange@redhat.com, armbru@redhat.com, stefanha@redhat.com, =?utf-8?q?Marc-Andr=C3=A9_Lureau?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Marc-André Lureau Add the build-sys infrastructure to build Rust code. Introduce a top-level workspace, so various sub-projects (libraries, executables etc) can be developed together, sharing the dependencies and output directory. If not Tier 1, many of the platforms QEMU supports are considered Tier 2: https://doc.rust-lang.org/nightly/rustc/platform-support.html Rust is generally available on various distributions (thanks to Firefox, I suppose). If not, it can usually be installed with rustup by developpers. configure will enable Rust support automatically if cargo is present. Rust support can be disabled --without-rust. When detecting windows cross building, it will use the $cpu-pc-windows-gnu target by default (more default mappings could be added over time). This can be changed with --with-rust-target=RTT. Signed-off-by: Marc-André Lureau --- Cargo.toml | 2 ++ configure | 18 ++++++++++++++++++ meson.build | 23 +++++++++++++++++++++++ 3 files changed, 43 insertions(+) create mode 100644 Cargo.toml diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000000..c4b464ff15 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,2 @@ +[workspace] +members = [] diff --git a/configure b/configure index b553288c5e..7945ceac63 100755 --- a/configure +++ b/configure @@ -446,6 +446,8 @@ meson="" ninja="" skip_meson=no gettext="" +with_rust="auto" +with_rust_target="" bogus_os="no" malloc_trim="auto" @@ -1519,6 +1521,12 @@ for opt do ;; --disable-libdaxctl) libdaxctl=no ;; + --with-rust) with_rust=yes + ;; + --without-rust) with_rust=no + ;; + --with-rust-target=*) with_rust_target="$optarg" + ;; *) echo "ERROR: unknown option $opt" echo "Try '$0 --help' for more information" @@ -1666,6 +1674,8 @@ Advanced options (experts only): --extra-ldflags=LDFLAGS append extra linker flags LDFLAGS --cross-cc-ARCH=CC use compiler when building ARCH guest test cases --cross-cc-flags-ARCH= use compiler flags when building ARCH guest tests + --with-rust enable Rust compilation + --with-rust-target=RTT use the given Rust target triple --make=MAKE use specified make [$make] --python=PYTHON use specified python [$python] --sphinx-build=SPHINX use specified sphinx-build [$sphinx_build] @@ -1918,6 +1928,10 @@ if test -z "$ninja"; then done fi +if test "$with_rust" = auto && has cargo; then + with_rust=yes +fi + # Check that the C compiler works. Doing this here before testing # the host CPU ensures that we had a valid CC to autodetect the # $cpu var (and we should bail right here if that's not the case). @@ -7046,6 +7060,10 @@ fi if test "$safe_stack" = "yes"; then echo "CONFIG_SAFESTACK=y" >> $config_host_mak fi +if test "$with_rust" = "yes" ; then + echo "CONFIG_WITH_RUST=y" >> $config_host_mak + echo "CONFIG_WITH_RUST_TARGET=$with_rust_target" >> $config_host_mak +fi # If we're using a separate build tree, set it up now. # DIRS are directories which we simply mkdir in the build tree; diff --git a/meson.build b/meson.build index 17c89c87c6..d8526dc999 100644 --- a/meson.build +++ b/meson.build @@ -73,6 +73,28 @@ if cpu in ['x86', 'x86_64'] } endif +with_rust = 'CONFIG_WITH_RUST' in config_host +cargo = find_program('cargo', required: with_rust) + +if with_rust + rs_target_triple = config_host['CONFIG_WITH_RUST_TARGET'] + if meson.is_cross_build() + # more default target mappings may be added over time + if rs_target_triple == '' and targetos == 'windows' + rs_target_triple = host_machine.cpu() + '-pc-windows-gnu' + endif + if rs_target_triple == '' + error('cross-compiling, but no Rust target-triple defined.') + endif + endif +endif + +if get_option('optimization') in ['0', '1', 'g'] + rs_build_type = 'debug' +else + rs_build_type = 'release' +endif + ################## # Compiler flags # ################## @@ -1770,6 +1792,7 @@ endif if targetos == 'darwin' summary_info += {'Objective-C compiler': meson.get_compiler('objc').cmd_array()[0]} endif +summary_info += {'Rust support': with_rust} summary_info += {'ARFLAGS': config_host['ARFLAGS']} summary_info += {'CFLAGS': ' '.join(get_option('c_args') + ['-O' + get_option('optimization')] From patchwork Sun Oct 11 20:35:02 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 271546 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-14.5 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, MENTIONS_GIT_HOSTING, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6BC2DC43457 for ; Sun, 11 Oct 2020 20:39:14 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 1A9E1207FB for ; Sun, 11 Oct 2020 20:39:14 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="J11BBcz6" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 1A9E1207FB Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:60208 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kRi7d-0005U3-7Z for qemu-devel@archiver.kernel.org; Sun, 11 Oct 2020 16:39:13 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:57376) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kRi4g-0000rU-4C for qemu-devel@nongnu.org; Sun, 11 Oct 2020 16:36:10 -0400 Received: from us-smtp-delivery-124.mimecast.com ([63.128.21.124]:48770) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1kRi4e-0005SJ-1D for qemu-devel@nongnu.org; Sun, 11 Oct 2020 16:36:09 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1602448567; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=95axpi0IvDfLnJZoXZHGJcKk2SIGdhXysMCYnQ2+U+Y=; b=J11BBcz6UKDT3DR/6gOyc9gu26LlelKHKaPTEMTyOx0a4sPTL/1/HEPzMHGaq3SZdvC9Vg F7DvV/7/AsmZpE1+61+CqWjEJFSk3It2hwn+TeJOJ1x9Rus8HD8qSovBGl8889lTBIEQyf kWr6yvBKl9F6DUDmPr1MJ5aWzP8NRGU= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-394-fYwgFLRaMW6Hr-fLflQp-g-1; Sun, 11 Oct 2020 16:36:01 -0400 X-MC-Unique: fYwgFLRaMW6Hr-fLflQp-g-1 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id E02F32FD02 for ; Sun, 11 Oct 2020 20:36:00 +0000 (UTC) Received: from localhost (unknown [10.36.110.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id 88D955DA30; Sun, 11 Oct 2020 20:35:59 +0000 (UTC) From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Subject: [PoCv2 04/15] build-sys: add a cargo-wrapper script Date: Mon, 12 Oct 2020 00:35:02 +0400 Message-Id: <20201011203513.1621355-5-marcandre.lureau@redhat.com> In-Reply-To: <20201011203513.1621355-1-marcandre.lureau@redhat.com> References: <20201011203513.1621355-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=marcandre.lureau@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=63.128.21.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/10/11 16:23:51 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -30 X-Spam_score: -3.1 X-Spam_bar: --- X-Spam_report: (-3.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=-1, RCVD_IN_MSPIKE_WL=-0.01, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: pbonzini@redhat.com, berrange@redhat.com, armbru@redhat.com, stefanha@redhat.com, =?utf-8?q?Marc-Andr=C3=A9_Lureau?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Marc-André Lureau Introduce a script to help calling cargo from Rust. Cargo is the most convenient way to build Rust code, with various crates, and has many features that meson lacks in general for Rust. Trying to convert projects to meson automatically is an option I considered (see for ex https://github.com/badboy/bygge for ninja conversion), but the complexity of the task and the need of build.rs mechanism in various crates makes this endeavour out of scope at this point. This script will help to invoke cargo in different ways. For now, it supports building static libraries. It sets up a common environment, run the compiler and grep its output for the linker flags. Finally it copies the built library to the expected meson output directory, and create a file with the linker arguments. Signed-off-by: Marc-André Lureau --- meson.build | 1 + scripts/cargo_wrapper.py | 101 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+) create mode 100644 scripts/cargo_wrapper.py diff --git a/meson.build b/meson.build index d8526dc999..c30bb290c5 100644 --- a/meson.build +++ b/meson.build @@ -75,6 +75,7 @@ endif with_rust = 'CONFIG_WITH_RUST' in config_host cargo = find_program('cargo', required: with_rust) +cargo_wrapper = find_program('scripts/cargo_wrapper.py') if with_rust rs_target_triple = config_host['CONFIG_WITH_RUST_TARGET'] diff --git a/scripts/cargo_wrapper.py b/scripts/cargo_wrapper.py new file mode 100644 index 0000000000..164fad5123 --- /dev/null +++ b/scripts/cargo_wrapper.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python3 +# Copyright (c) 2020 Red Hat, Inc. +# +# Author: +# Marc-André Lureau +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +import argparse +import configparser +import distutils.file_util +import glob +import os +import os.path +import re +import subprocess +import sys +from typing import List + + +def get_cargo_target_dir(args: argparse.Namespace) -> str: + # avoid conflict with qemu "target" directory + return os.path.join(args.build_dir, "rs-target") + + +def get_manifest_path(args: argparse.Namespace) -> str: + return os.path.join(args.src_dir, "Cargo.toml") + + +def build_lib(args: argparse.Namespace) -> None: + target_dir = get_cargo_target_dir(args) + manifest_path = get_manifest_path(args) + # let's pretend it's an INI file to avoid extra dependency + config = configparser.ConfigParser() + config.read(manifest_path) + package_name = config["package"]["name"].strip('"') + liba = os.path.join( + target_dir, args.target_triple, args.build_type, "lib" + package_name + ".a" + ) + libargs = os.path.join(args.build_dir, "lib" + package_name + ".args") + + env = {} + env["MESON_CURRENT_BUILD_DIR"] = args.build_dir + env["MESON_BUILD_ROOT"] = args.build_root + env["WINAPI_NO_BUNDLED_LIBRARIES"] = "1" + cargo_cmd = [ + "cargo", + "rustc", + "--target-dir", + target_dir, + "--manifest-path", + manifest_path, + ] + if args.target_triple: + cargo_cmd += ["--target", args.target_triple] + if args.build_type == "release": + cargo_cmd += ["--release"] + cargo_cmd += ["--", "--print", "native-static-libs"] + cargo_cmd += args.EXTRA + try: + out = subprocess.check_output( + cargo_cmd, + env=dict(os.environ, **env), + stderr=subprocess.STDOUT, + universal_newlines=True, + ) + native_static_libs = re.search(r"native-static-libs:(.*)", out) + link_args = native_static_libs.group(1) + with open(libargs, "w") as f: + print(link_args, file=f) + + distutils.file_util.copy_file(liba, args.build_dir, update=True) + except subprocess.CalledProcessError as e: + print( + "Environment: " + " ".join(["{}={}".format(k, v) for k, v in env.items()]) + ) + print("Command: " + " ".join(cargo_cmd)) + print(e.output) + sys.exit(1) + + +def main() -> None: + parser = argparse.ArgumentParser() + parser.add_argument("command") + parser.add_argument("build_dir") + parser.add_argument("src_dir") + parser.add_argument("build_root") + parser.add_argument("build_type") + parser.add_argument("target_triple") + parser.add_argument("EXTRA", nargs="*") + args = parser.parse_args() + + if args.command == "build-lib": + build_lib(args) + else: + raise argparse.ArgumentTypeError("Unknown command: %s" % args.command) + + +if __name__ == "__main__": + main() From patchwork Sun Oct 11 20:35:03 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 271547 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D5E1FC433DF for ; Sun, 11 Oct 2020 20:39:11 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 791EA207FB for ; Sun, 11 Oct 2020 20:39:11 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="VDWDE7X8" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 791EA207FB Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:59892 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kRi7a-0005MH-Ht for qemu-devel@archiver.kernel.org; Sun, 11 Oct 2020 16:39:10 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:57444) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kRi4q-00012b-TD for qemu-devel@nongnu.org; Sun, 11 Oct 2020 16:36:21 -0400 Received: from us-smtp-delivery-124.mimecast.com ([63.128.21.124]:32174) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1kRi4m-0005UA-Vx for qemu-devel@nongnu.org; Sun, 11 Oct 2020 16:36:19 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1602448575; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=OHft3RD80FkUI2fpCOWT/+7Xhsx9FIeU/vkqD1Xscrk=; b=VDWDE7X8u37yYQSuN5vg2swYu05L7ACnMyaf6AQcnIy59Iy5ZGcuqqhzaSpFdwz8U4p5SJ pu6Pu/jdY79oyHdXsX9nE8hi0TQYq36Gv7PbDcZpS7sm3mQJBNKBURZXOpo/nYh81lp5sJ irIe84l3OGTY2HnQvIOZAyjoW84MN3w= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-284-d9gvnVZqNh6Ri1XzLgyBEA-1; Sun, 11 Oct 2020 16:36:12 -0400 X-MC-Unique: d9gvnVZqNh6Ri1XzLgyBEA-1 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 72071107ACF5 for ; Sun, 11 Oct 2020 20:36:11 +0000 (UTC) Received: from localhost (unknown [10.36.110.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id DF06B55790; Sun, 11 Oct 2020 20:36:04 +0000 (UTC) From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Subject: [PoCv2 05/15] qga/rust: build and link an empty static library Date: Mon, 12 Oct 2020 00:35:03 +0400 Message-Id: <20201011203513.1621355-6-marcandre.lureau@redhat.com> In-Reply-To: <20201011203513.1621355-1-marcandre.lureau@redhat.com> References: <20201011203513.1621355-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=marcandre.lureau@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=63.128.21.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/10/11 16:23:51 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -30 X-Spam_score: -3.1 X-Spam_bar: --- X-Spam_report: (-3.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=-1, RCVD_IN_MSPIKE_WL=-0.01, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: pbonzini@redhat.com, berrange@redhat.com, armbru@redhat.com, stefanha@redhat.com, =?utf-8?q?Marc-Andr=C3=A9_Lureau?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Marc-André Lureau Meson doesn't integrate very smoothly with Cargo. Use the cargo-wrapper script as a custom_target() always stale to build the Rust code. The "build-lib" command will produce a static library in the meson expected output directory, as well as link flags that must be employed to do the final link. Those link flags can't be queried during configure time (Cargo doesn't have a user-queriable configure step), so we pass them to the linker thanks to @file argument support at build time. Signed-off-by: Marc-André Lureau --- Cargo.toml | 2 +- qga/Cargo.toml | 9 +++++++++ qga/lib.rs | 0 qga/meson.build | 18 +++++++++++++++++- 4 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 qga/Cargo.toml create mode 100644 qga/lib.rs diff --git a/Cargo.toml b/Cargo.toml index c4b464ff15..e69b04200f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,2 +1,2 @@ [workspace] -members = [] +members = ["qga"] diff --git a/qga/Cargo.toml b/qga/Cargo.toml new file mode 100644 index 0000000000..50c3415ab2 --- /dev/null +++ b/qga/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "qga" +version = "0.1.0" +edition = "2018" +license = "GPLv2" + +[lib] +path = "lib.rs" +crate-type = ["staticlib"] diff --git a/qga/lib.rs b/qga/lib.rs new file mode 100644 index 0000000000..e69de29bb2 diff --git a/qga/meson.build b/qga/meson.build index cd08bd953a..62e13a11b3 100644 --- a/qga/meson.build +++ b/qga/meson.build @@ -45,9 +45,25 @@ qga_ss.add(when: 'CONFIG_WIN32', if_true: files( qga_ss = qga_ss.apply(config_host, strict: false) +qga_rs = declare_dependency() +if with_rust + cargo_qga = custom_target('cargo-qga', + build_by_default: true, + output: ['libqga.args', 'libqga.a'], + build_always_stale: true, + command: [cargo_wrapper, + 'build-lib', + meson.current_build_dir(), + meson.current_source_dir(), + meson.build_root(), + rs_build_type, + rs_target_triple]) + qga_rs = declare_dependency(link_args: '@' + cargo_qga.full_path(), sources: cargo_qga) +endif + qga = executable('qemu-ga', qga_ss.sources(), link_args: config_host['LIBS_QGA'].split(), - dependencies: [qemuutil, libudev], + dependencies: [qemuutil, libudev, qga_rs], install: true) all_qga = [qga] From patchwork Sun Oct 11 20:35:04 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 303140 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.5 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 78BC6C433E7 for ; Sun, 11 Oct 2020 20:41:29 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 0E07F207FB for ; Sun, 11 Oct 2020 20:41:29 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="Ri/CRzxZ" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 0E07F207FB Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:40314 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kRi9o-0000rn-3V for qemu-devel@archiver.kernel.org; Sun, 11 Oct 2020 16:41:28 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:57456) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kRi4w-00017H-La for qemu-devel@nongnu.org; Sun, 11 Oct 2020 16:36:28 -0400 Received: from us-smtp-delivery-124.mimecast.com ([63.128.21.124]:50385) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1kRi4s-0005UK-GC for qemu-devel@nongnu.org; Sun, 11 Oct 2020 16:36:26 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1602448580; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=oMGcivtxqfyttrxW+n4YbT+qnoQcOtRjXxzV/2OSLnk=; b=Ri/CRzxZoyxrVcz8252OYAOLlwRIYsiVVw4PkoKIhp3+4YbLFO98Wpot6EZarBQlt/LKlh v6E2IjQgtMPQnjFiUz7+YPC9gmBnkVyOtjjzzKWSQq35QgLzhe22g/empOhAxNSjDywhnr 764iqt1hXkToc8Dzp8RvPkrLQDngbyU= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-306-o_2hRVGHMz-OOlPLfEgsFA-1; Sun, 11 Oct 2020 16:36:18 -0400 X-MC-Unique: o_2hRVGHMz-OOlPLfEgsFA-1 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id C77DF804001 for ; Sun, 11 Oct 2020 20:36:17 +0000 (UTC) Received: from localhost (unknown [10.36.110.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id 8C8D67512E; Sun, 11 Oct 2020 20:36:15 +0000 (UTC) From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Subject: [PoCv2 06/15] rust: provide a common crate for QEMU Date: Mon, 12 Oct 2020 00:35:04 +0400 Message-Id: <20201011203513.1621355-7-marcandre.lureau@redhat.com> In-Reply-To: <20201011203513.1621355-1-marcandre.lureau@redhat.com> References: <20201011203513.1621355-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=marcandre.lureau@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=63.128.21.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/10/11 16:23:51 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -30 X-Spam_score: -3.1 X-Spam_bar: --- X-Spam_report: (-3.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=-1, RCVD_IN_MSPIKE_WL=-0.01, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: pbonzini@redhat.com, berrange@redhat.com, armbru@redhat.com, stefanha@redhat.com, =?utf-8?q?Marc-Andr=C3=A9_Lureau?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Marc-André Lureau This crates provides common bindings and facilities for QEMU C API shared by various projects. Most importantly, it defines the conversion traits used to convert from C to Rust types. Those traits are largely adapted from glib-rs, since those have prooven to be very flexible, and should guide us to bind further QEMU types such as QOM. If glib-rs becomes a dependency, we should consider adopting glib translate traits. For QAPI, we need a smaller subset. Signed-off-by: Marc-André Lureau --- Cargo.toml | 5 +- rust/common/Cargo.toml | 11 ++ rust/common/src/error.rs | 109 ++++++++++++ rust/common/src/lib.rs | 10 ++ rust/common/src/qemu.rs | 30 ++++ rust/common/src/sys.rs | 58 +++++++ rust/common/src/translate.rs | 309 +++++++++++++++++++++++++++++++++++ 7 files changed, 531 insertions(+), 1 deletion(-) create mode 100644 rust/common/Cargo.toml create mode 100644 rust/common/src/error.rs create mode 100644 rust/common/src/lib.rs create mode 100644 rust/common/src/qemu.rs create mode 100644 rust/common/src/sys.rs create mode 100644 rust/common/src/translate.rs diff --git a/Cargo.toml b/Cargo.toml index e69b04200f..26bd083f79 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,2 +1,5 @@ [workspace] -members = ["qga"] +members = [ + "qga", + "rust/common", +] diff --git a/rust/common/Cargo.toml b/rust/common/Cargo.toml new file mode 100644 index 0000000000..f0584dcc83 --- /dev/null +++ b/rust/common/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "common" +version = "0.1.0" +edition = "2018" +license = "GPLv2" + +[dependencies] +libc = "^0.2.76" + +[target."cfg(unix)".dependencies] +nix = "^0.18.0" diff --git a/rust/common/src/error.rs b/rust/common/src/error.rs new file mode 100644 index 0000000000..b89f788833 --- /dev/null +++ b/rust/common/src/error.rs @@ -0,0 +1,109 @@ +use std::{self, ffi, fmt, io, ptr}; + +use crate::translate::*; +use crate::{qemu, sys}; + +/// Common error type for QEMU and related projects. +#[derive(Debug)] +pub enum Error { + FailedAt(String, &'static str, u32), + Io(io::Error), + #[cfg(unix)] + Nix(nix::Error), +} + +/// Alias for a `Result` with the error type for QEMU. +pub type Result = std::result::Result; + +impl Error { + fn message(&self) -> String { + use Error::*; + match self { + FailedAt(msg, _, _) => msg.into(), + Io(io) => format!("IO error: {}", io), + #[cfg(unix)] + Nix(nix) => format!("Nix error: {}", nix), + } + } + + fn location(&self) -> Option<(&'static str, u32)> { + use Error::*; + match self { + FailedAt(_, file, line) => Some((file, *line)), + Io(_) => None, + #[cfg(unix)] + Nix(_) => None, + } + } +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use Error::*; + match self { + FailedAt(msg, file, line) => write!(f, "{} ({}:{})", msg, file, line), + _ => write!(f, "{}", self.message()), + } + } +} + +impl From for Error { + fn from(val: io::Error) -> Self { + Error::Io(val) + } +} + +#[cfg(unix)] +impl From for Error { + fn from(val: nix::Error) -> Self { + Error::Nix(val) + } +} + +impl QemuPtrDefault for Error { + type QemuType = *mut sys::Error; +} + +impl<'a> ToQemuPtr<'a, *mut sys::Error> for Error { + type Storage = qemu::CError; + + fn to_qemu_none(&'a self) -> Stash<'a, *mut sys::Error, Self> { + let err = self.to_qemu_full(); + + Stash(err, unsafe { from_qemu_full(err) }) + } + + fn to_qemu_full(&self) -> *mut sys::Error { + let cmsg = + ffi::CString::new(self.message()).expect("ToQemuPtr: unexpected '\0' character"); + let mut csrc = ffi::CString::new("").unwrap(); + let (src, line) = self.location().map_or((ptr::null(), 0 as i32), |loc| { + csrc = ffi::CString::new(loc.0).expect("ToQemuPtr:: unexpected '\0' character"); + (csrc.as_ptr() as *const libc::c_char, loc.1 as i32) + }); + let func = ptr::null(); + + let mut err: *mut sys::Error = ptr::null_mut(); + unsafe { + sys::error_setg_internal( + &mut err as *mut *mut _, + src, + line, + func, + cmsg.as_ptr() as *const libc::c_char, + ); + err + } + } +} + +/// Convenience macro to build a `Error::FailedAt` error. +/// +/// (this error type can be nicely converted to a QEMU `sys::Error`) +#[allow(unused_macros)] +#[macro_export] +macro_rules! err { + ($err:expr) => { + Err(Error::FailedAt($err.into(), file!(), line!())) + }; +} diff --git a/rust/common/src/lib.rs b/rust/common/src/lib.rs new file mode 100644 index 0000000000..2632a2b92b --- /dev/null +++ b/rust/common/src/lib.rs @@ -0,0 +1,10 @@ +mod error; +pub use error::*; + +mod qemu; +pub use qemu::*; + +mod translate; +pub use translate::*; + +pub mod sys; diff --git a/rust/common/src/qemu.rs b/rust/common/src/qemu.rs new file mode 100644 index 0000000000..e1e47d3623 --- /dev/null +++ b/rust/common/src/qemu.rs @@ -0,0 +1,30 @@ +use std::{ffi::CStr, ptr, str}; + +use crate::{sys, translate}; + +/// A type representing an owned C QEMU Error. +pub struct CError(ptr::NonNull); + +impl translate::FromQemuPtrFull<*mut sys::Error> for CError { + unsafe fn from_qemu_full(ptr: *mut sys::Error) -> Self { + assert!(!ptr.is_null()); + Self(ptr::NonNull::new_unchecked(ptr)) + } +} + +impl CError { + pub fn pretty(&self) -> &str { + unsafe { + let pretty = sys::error_get_pretty(self.0.as_ptr()); + let bytes = CStr::from_ptr(pretty).to_bytes(); + str::from_utf8(bytes) + .unwrap_or_else(|err| str::from_utf8(&bytes[..err.valid_up_to()]).unwrap()) + } + } +} + +impl Drop for CError { + fn drop(&mut self) { + unsafe { sys::error_free(self.0.as_ptr()) } + } +} diff --git a/rust/common/src/sys.rs b/rust/common/src/sys.rs new file mode 100644 index 0000000000..de37144860 --- /dev/null +++ b/rust/common/src/sys.rs @@ -0,0 +1,58 @@ +//! Bindings to the raw low-level C API commonly provided by QEMU projects. +//! +//! Manual bindings to C API availabe when linking QEMU projects. +//! It includes minimal glib allocation functions too, since it's the default +//! allocator used by QEMU, and we don't depend on glib-rs crate yet). +//! +//! Higher-level Rust-friendly bindings are provided by different modules. + +use libc::{c_char, c_void, size_t}; + +extern "C" { + pub fn g_malloc0(n_bytes: size_t) -> *mut c_void; + pub fn g_free(ptr: *mut c_void); + pub fn g_strndup(str: *const c_char, n: size_t) -> *mut c_char; +} + +#[repr(C)] +pub struct QObject(c_void); + +impl ::std::fmt::Debug for QObject { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + f.debug_struct(&format!("QObject @ {:?}", self as *const _)) + .finish() + } +} + +#[repr(C)] +pub struct QNull(c_void); + +impl ::std::fmt::Debug for QNull { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + f.debug_struct(&format!("QNull @ {:?}", self as *const _)) + .finish() + } +} + +#[repr(C)] +pub struct Error(c_void); + +impl ::std::fmt::Debug for Error { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + f.debug_struct(&format!("Error @ {:?}", self as *const _)) + .finish() + } +} + +extern "C" { + pub fn error_setg_internal( + errp: *mut *mut Error, + src: *const c_char, + line: i32, + func: *const c_char, + fmt: *const c_char, + ... + ); + pub fn error_get_pretty(err: *const Error) -> *const c_char; + pub fn error_free(err: *mut Error); +} diff --git a/rust/common/src/translate.rs b/rust/common/src/translate.rs new file mode 100644 index 0000000000..3be6e91987 --- /dev/null +++ b/rust/common/src/translate.rs @@ -0,0 +1,309 @@ +// largely adapted from glib-rs +// we don't depend on glib-rs as this brings a lot more code that we may not need +// and also because there are issues with the conversion traits for our sys::*mut. +use libc::{c_char, size_t}; +use std::ffi::{CStr, CString}; +use std::ptr; + +use crate::sys; + +/// A pointer. +pub trait Ptr: Copy + 'static { + fn is_null(&self) -> bool; + fn from(ptr: *mut X) -> Self; + fn to(self) -> *mut X; +} + +impl Ptr for *const T { + #[inline] + fn is_null(&self) -> bool { + (*self).is_null() + } + + #[inline] + fn from(ptr: *mut X) -> *const T { + ptr as *const T + } + + #[inline] + fn to(self) -> *mut X { + self as *mut X + } +} + +impl Ptr for *mut T { + #[inline] + fn is_null(&self) -> bool { + (*self).is_null() + } + + #[inline] + fn from(ptr: *mut X) -> *mut T { + ptr as *mut T + } + + #[inline] + fn to(self) -> *mut X { + self as *mut X + } +} + +/// Macro for NewPtr. +/// +/// A macro to declare a newtype for pointers, to workaround that *T are not +/// defined in our binding crates, and allow foreign traits implementations. +/// (this is used by qapi-gen bindings) +#[allow(unused_macros)] +#[macro_export] +macro_rules! new_ptr { + () => { + #[derive(Copy, Clone)] + pub struct NewPtr(pub P); + + impl Ptr for NewPtr

{ + #[inline] + fn is_null(&self) -> bool { + self.0.is_null() + } + + #[inline] + fn from(ptr: *mut X) -> Self { + NewPtr(P::from(ptr)) + } + + #[inline] + fn to(self) -> *mut X { + self.0.to() + } + } + }; +} + +/// Provides the default pointer type to be used in some container conversions. +/// +/// It's `*mut c_char` for `String`, `*mut sys::GuestInfo` for `GuestInfo`... +pub trait QemuPtrDefault { + type QemuType: Ptr; +} + +impl QemuPtrDefault for String { + type QemuType = *mut c_char; +} + +pub struct Stash<'a, P: Copy, T: ?Sized + ToQemuPtr<'a, P>>( + pub P, + pub >::Storage, +); + +/// Translate to a pointer. +pub trait ToQemuPtr<'a, P: Copy> { + type Storage; + + /// The pointer in the `Stash` is only valid for the lifetime of the `Stash`. + fn to_qemu_none(&'a self) -> Stash<'a, P, Self>; + + /// Transfer the ownership to the ffi. + fn to_qemu_full(&self) -> P { + unimplemented!(); + } +} + +impl<'a, P: Ptr, T: ToQemuPtr<'a, P>> ToQemuPtr<'a, P> for Option { + type Storage = Option<>::Storage>; + + #[inline] + fn to_qemu_none(&'a self) -> Stash<'a, P, Option> { + self.as_ref() + .map_or(Stash(Ptr::from::<()>(ptr::null_mut()), None), |s| { + let s = s.to_qemu_none(); + Stash(s.0, Some(s.1)) + }) + } + + #[inline] + fn to_qemu_full(&self) -> P { + self.as_ref() + .map_or(Ptr::from::<()>(ptr::null_mut()), ToQemuPtr::to_qemu_full) + } +} + +impl<'a> ToQemuPtr<'a, *mut c_char> for String { + type Storage = CString; + + #[inline] + fn to_qemu_none(&self) -> Stash<'a, *mut c_char, String> { + let tmp = CString::new(&self[..]) + .expect("String::ToQemuPtr<*mut c_char>: unexpected '\0' character"); + Stash(tmp.as_ptr() as *mut c_char, tmp) + } + + #[inline] + fn to_qemu_full(&self) -> *mut c_char { + unsafe { sys::g_strndup(self.as_ptr() as *const c_char, self.len() as size_t) } + } +} + +/// Translate from a pointer type, without taking ownership. +pub trait FromQemuPtrNone: Sized { + /// # Safety + /// + /// `ptr` must be a valid pointer. It is not referenced after the call. + unsafe fn from_qemu_none(ptr: P) -> Self; +} + +/// Translate from a pointer type, taking ownership. +pub trait FromQemuPtrFull: Sized { + /// # Safety + /// + /// `ptr` must be a valid pointer. Ownership is transferred. + unsafe fn from_qemu_full(ptr: P) -> Self; +} + +/// See [`FromQemuPtrNone`](trait.FromQemuPtrNone.html). +#[inline] +#[allow(clippy::missing_safety_doc)] +pub unsafe fn from_qemu_none>(ptr: P) -> T { + FromQemuPtrNone::from_qemu_none(ptr) +} + +/// See [`FromQemuPtrFull`](trait.FromQemuPtrFull.html). +#[inline] +#[allow(clippy::missing_safety_doc)] +pub unsafe fn from_qemu_full>(ptr: P) -> T { + FromQemuPtrFull::from_qemu_full(ptr) +} + +impl> FromQemuPtrNone

for Option { + #[inline] + unsafe fn from_qemu_none(ptr: P) -> Option { + if ptr.is_null() { + None + } else { + Some(from_qemu_none(ptr)) + } + } +} + +impl> FromQemuPtrFull

for Option { + #[inline] + unsafe fn from_qemu_full(ptr: P) -> Option { + if ptr.is_null() { + None + } else { + Some(from_qemu_full(ptr)) + } + } +} + +impl FromQemuPtrNone<*const c_char> for String { + #[inline] + unsafe fn from_qemu_none(ptr: *const c_char) -> Self { + assert!(!ptr.is_null()); + String::from_utf8_lossy(CStr::from_ptr(ptr).to_bytes()).into_owned() + } +} + +impl FromQemuPtrFull<*mut c_char> for String { + #[inline] + unsafe fn from_qemu_full(ptr: *mut c_char) -> Self { + let res = from_qemu_none(ptr as *const _); + sys::g_free(ptr as *mut _); + res + } +} + +/// A macro to help the implementation of `Vec -> P` translations. +#[allow(unused_macros)] +#[macro_export] +macro_rules! vec_to_qemu { + ($rs:ident, $sys:ident) => { + #[allow(non_camel_case_types)] + pub struct $sys(*mut qapi_sys::$sys); + + impl Drop for $sys { + fn drop(&mut self) { + let mut list = self.0; + unsafe { + while !list.is_null() { + let next = (*list).next; + Box::from_raw(list); + list = next; + } + } + } + } + + impl<'a> ToQemuPtr<'a, NewPtr<*mut qapi_sys::$sys>> for Vec<$rs> { + type Storage = ( + Option<$sys>, + Vec::QemuType, $rs>>, + ); + + #[inline] + fn to_qemu_none(&self) -> Stash, Self> { + let stash_vec: Vec<_> = self.iter().rev().map(ToQemuPtr::to_qemu_none).collect(); + let mut list: *mut qapi_sys::$sys = std::ptr::null_mut(); + for stash in &stash_vec { + let b = Box::new(qapi_sys::$sys { + next: list, + value: Ptr::to(stash.0), + }); + list = Box::into_raw(b); + } + Stash(NewPtr(list), (Some($sys(list)), stash_vec)) + } + + #[inline] + fn to_qemu_full(&self) -> NewPtr<*mut qapi_sys::$sys> { + let v: Vec<_> = self.iter().rev().map(ToQemuPtr::to_qemu_full).collect(); + let mut list: *mut qapi_sys::$sys = std::ptr::null_mut(); + unsafe { + for val in v { + let l = sys::g_malloc0(std::mem::size_of::()) + as *mut qapi_sys::$sys; + (*l).next = list; + (*l).value = val; + list = l; + } + } + NewPtr(list) + } + } + }; +} + +/// A macro to help the implementation of `P -> Vec` translations. +#[allow(unused_macros)] +#[macro_export] +macro_rules! vec_from_qemu { + ($rs:ident, $sys:ident, $free_sys:ident) => { + impl FromQemuPtrFull> for Vec<$rs> { + #[inline] + unsafe fn from_qemu_full(sys: NewPtr<*mut qapi_sys::$sys>) -> Self { + let ret = from_qemu_none(NewPtr(sys.0 as *const _)); + qapi_sys::$free_sys(sys.0); + ret + } + } + + impl FromQemuPtrNone> for Vec<$rs> { + #[inline] + unsafe fn from_qemu_none(sys: NewPtr<*const qapi_sys::$sys>) -> Self { + let mut ret = vec![]; + let mut it = sys.0; + while !it.is_null() { + let e = &*it; + ret.push(from_qemu_none(e.value as *const _)); + it = e.next; + } + ret + } + } + + impl From> for *mut qapi_sys::$sys { + fn from(p: NewPtr<*mut qapi_sys::$sys>) -> Self { + p.0 + } + } + }; +} From patchwork Sun Oct 11 20:35:05 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 271543 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.5 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 74E0DC433DF for ; Sun, 11 Oct 2020 20:44:58 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id ED07420578 for ; Sun, 11 Oct 2020 20:44:57 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="G+MNG+0Z" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org ED07420578 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:48834 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kRiDB-0004eu-2Y for qemu-devel@archiver.kernel.org; Sun, 11 Oct 2020 16:44:57 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:57498) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kRi57-0001Lz-0I for qemu-devel@nongnu.org; Sun, 11 Oct 2020 16:36:37 -0400 Received: from us-smtp-delivery-124.mimecast.com ([63.128.21.124]:48402) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1kRi54-0005Vg-5S for qemu-devel@nongnu.org; Sun, 11 Oct 2020 16:36:36 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1602448593; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=//HZmmfSPMGK7ml0gSGQZp5T/TptKbriYwAwFbDujNk=; b=G+MNG+0ZC3lP0EYoWpqrkASKhIwdcZPfYLd/qU87zavq2VvS4gCwQ35SsWLsyqVqbj4cV4 0gO8EOQGqwFen4XXmIJRU8cTf+dq8A5xsnUP2qkxiVEnFRng4x3IoIo0lonLEhiFYW2D0W RN0nXGBLbbt51gCY3x/9f3DhsLgInY4= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-262-F5R_kDxNOm-V_xii7kjIeg-1; Sun, 11 Oct 2020 16:36:30 -0400 X-MC-Unique: F5R_kDxNOm-V_xii7kjIeg-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 44F1D10066FB for ; Sun, 11 Oct 2020 20:36:29 +0000 (UTC) Received: from localhost (unknown [10.36.110.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id C7F106EF7E; Sun, 11 Oct 2020 20:36:21 +0000 (UTC) From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Subject: [PoCv2 07/15] scripts/qapi: add Rust sys bindings generation Date: Mon, 12 Oct 2020 00:35:05 +0400 Message-Id: <20201011203513.1621355-8-marcandre.lureau@redhat.com> In-Reply-To: <20201011203513.1621355-1-marcandre.lureau@redhat.com> References: <20201011203513.1621355-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=marcandre.lureau@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=63.128.21.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/10/11 16:23:51 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -30 X-Spam_score: -3.1 X-Spam_bar: --- X-Spam_report: (-3.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=-1, RCVD_IN_MSPIKE_WL=-0.01, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: pbonzini@redhat.com, berrange@redhat.com, armbru@redhat.com, stefanha@redhat.com, =?utf-8?q?Marc-Andr=C3=A9_Lureau?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Marc-André Lureau Generate the C QAPI types in Rust, with a few common niceties to Debug/Clone/Copy the Rust type. An important question that remains unsolved to be usable with the QEMU schema in this version, is the handling of the 'if' compilation conditions. Since the 'if' value is a C pre-processor condition, it is hard to evaluate from Rust (we could implement a minimalistic CPP evaluator, or invoke CPP and somehow parse the output...). The normal Rust way of handling conditional compilation is via #[cfg] features, which rely on feature arguments being passed to rustc from Cargo. This would require a long Rust feature list, and new 'if-cfg' conditions in the schema (an idea would be for Cargo to read features from meson in the future?) Signed-off-by: Marc-André Lureau --- meson.build | 4 +- scripts/qapi-gen.py | 16 ++- scripts/qapi/rs.py | 126 ++++++++++++++++++++ scripts/qapi/rs_sys.py | 254 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 394 insertions(+), 6 deletions(-) create mode 100644 scripts/qapi/rs.py create mode 100644 scripts/qapi/rs_sys.py diff --git a/meson.build b/meson.build index c30bb290c5..b6b8330b97 100644 --- a/meson.build +++ b/meson.build @@ -1147,7 +1147,9 @@ qapi_gen_depends = [ meson.source_root() / 'scripts/qapi/__init__.py', meson.source_root() / 'scripts/qapi/types.py', meson.source_root() / 'scripts/qapi/visit.py', meson.source_root() / 'scripts/qapi/common.py', - meson.source_root() / 'scripts/qapi-gen.py' + meson.source_root() / 'scripts/qapi/rs.py', + meson.source_root() / 'scripts/qapi/rs_sys.py', + meson.source_root() / 'scripts/qapi-gen.py', ] tracetool = [ diff --git a/scripts/qapi-gen.py b/scripts/qapi-gen.py index 541e8c1f55..5bfe9c8cd1 100644 --- a/scripts/qapi-gen.py +++ b/scripts/qapi-gen.py @@ -16,10 +16,13 @@ from qapi.schema import QAPIError, QAPISchema from qapi.types import gen_types from qapi.visit import gen_visit +from qapi.rs_sys import gen_rs_systypes def main(argv): parser = argparse.ArgumentParser( description='Generate code from a QAPI schema') + parser.add_argument('-r', '--rust', action='store_true', + help="generate Rust code") parser.add_argument('-b', '--builtins', action='store_true', help="generate code for built-in types") parser.add_argument('-o', '--output-dir', action='store', default='', @@ -45,11 +48,14 @@ def main(argv): print(err, file=sys.stderr) exit(1) - gen_types(schema, args.output_dir, args.prefix, args.builtins) - gen_visit(schema, args.output_dir, args.prefix, args.builtins) - gen_commands(schema, args.output_dir, args.prefix) - gen_events(schema, args.output_dir, args.prefix) - gen_introspect(schema, args.output_dir, args.prefix, args.unmask) + if args.rust: + gen_rs_systypes(schema, args.output_dir, args.prefix, args.builtins) + else: + gen_types(schema, args.output_dir, args.prefix, args.builtins) + gen_visit(schema, args.output_dir, args.prefix, args.builtins) + gen_commands(schema, args.output_dir, args.prefix) + gen_events(schema, args.output_dir, args.prefix) + gen_introspect(schema, args.output_dir, args.prefix, args.unmask) if __name__ == '__main__': diff --git a/scripts/qapi/rs.py b/scripts/qapi/rs.py new file mode 100644 index 0000000000..daa946580b --- /dev/null +++ b/scripts/qapi/rs.py @@ -0,0 +1,126 @@ +# This work is licensed under the terms of the GNU GPL, version 2. +# See the COPYING file in the top-level directory. +""" +QAPI Rust generator +""" + +import os +import subprocess + +from qapi.common import * +from qapi.gen import QAPIGen, QAPISchemaVisitor + + +rs_name_trans = str.maketrans('.-', '__') + +# Map @name to a valid Rust identifier. +# If @protect, avoid returning certain ticklish identifiers (like +# keywords) by prepending raw identifier prefix 'r#'. +def rs_name(name, protect=True): + name = name.translate(rs_name_trans) + if name[0].isnumeric(): + name = '_' + name + if not protect: + return name + # based from the list: + # https://doc.rust-lang.org/reference/keywords.html + if name in ('Self', 'abstract', 'as', 'async', + 'await','become', 'box', 'break', + 'const', 'continue', 'crate', 'do', + 'dyn', 'else', 'enum', 'extern', + 'false', 'final', 'fn', 'for', + 'if', 'impl', 'in', 'let', + 'loop', 'macro', 'match', 'mod', + 'move', 'mut', 'override', 'priv', + 'pub', 'ref', 'return', 'self', + 'static', 'struct', 'super', 'trait', + 'true', 'try', 'type', 'typeof', + 'union', 'unsafe', 'unsized', 'use', + 'virtual', 'where', 'while', 'yield', + ): + name = 'r#' + name + return name + + +def rs_ctype_parse(c_type): + is_pointer = False + if c_type.endswith(pointer_suffix): + is_pointer = True + c_type = c_type.rstrip(pointer_suffix).strip() + is_list = c_type.endswith('List') + is_const = False + if c_type.startswith('const '): + is_const = True + c_type = c_type[6:] + + return (is_pointer, is_const, is_list, c_type) + + +def rs_systype(c_type, sys_ns='qapi_sys::', list_as_newp=False): + (is_pointer, is_const, is_list, c_type) = rs_ctype_parse(c_type) + + to_rs = { + 'char': 'libc::c_char', + 'int8_t': 'i8', + 'uint8_t': 'u8', + 'int16_t': 'i16', + 'uint16_t': 'u16', + 'int32_t': 'i32', + 'uint32_t': 'u32', + 'int64_t': 'libc::c_longlong', + 'uint64_t': 'libc::c_ulonglong', + 'double': 'libc::c_double', + 'bool': 'bool', + } + + rs = '' + if is_const and is_pointer: + rs += '*const ' + elif is_pointer: + rs += '*mut ' + if c_type in to_rs: + rs += to_rs[c_type] + else: + rs += sys_ns + c_type + + if is_list and list_as_newp: + rs = 'NewPtr<{}>'.format(rs) + + return rs + + +def to_camel_case(value): + if value[0] == '_': + return value + raw_id = False + if value.startswith('r#'): + raw_id = True + value = value[2:] + value = ''.join(word.title() for word in filter(None, re.split("[-_]+", value))) + if raw_id: + return 'r#' + value + else: + return value + + +class QAPIGenRs(QAPIGen): + + def __init__(self, fname): + super().__init__(fname) + + +class QAPISchemaRsVisitor(QAPISchemaVisitor): + + def __init__(self, prefix, what): + self._prefix = prefix + self._what = what + self._gen = QAPIGenRs(self._prefix + self._what + '.rs') + + def write(self, output_dir): + self._gen.write(output_dir) + + pathname = os.path.join(output_dir, self._gen.fname) + try: + subprocess.check_call(['rustfmt', pathname]) + except FileNotFoundError: + pass diff --git a/scripts/qapi/rs_sys.py b/scripts/qapi/rs_sys.py new file mode 100644 index 0000000000..551a910c57 --- /dev/null +++ b/scripts/qapi/rs_sys.py @@ -0,0 +1,254 @@ +# This work is licensed under the terms of the GNU GPL, version 2. +# See the COPYING file in the top-level directory. +""" +QAPI Rust sys/ffi generator +""" + +from qapi.common import * +from qapi.rs import * +from qapi.schema import QAPISchemaEnumMember, QAPISchemaObjectType + + +objects_seen = set() + + +def gen_rs_sys_enum(name, ifcond, members, prefix=None): + if ifcond: + raise NotImplementedError("ifcond are not implemented") + # append automatically generated _max value + enum_members = members + [QAPISchemaEnumMember('_MAX', None)] + + ret = mcgen(''' + +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +#[repr(C)] +pub enum %(rs_name)s { +''', + rs_name=rs_name(name)) + + for m in enum_members: + if m.ifcond: + raise NotImplementedError("ifcond are not implemented") + ret += mcgen(''' + %(c_enum)s, +''', + c_enum=to_camel_case(rs_name(m.name, False))) + ret += mcgen(''' +} +''') + return ret + + +def gen_rs_sys_struct_members(members): + ret = '' + for memb in members: + if memb.ifcond: + raise NotImplementedError("ifcond are not implemented") + if memb.optional: + ret += mcgen(''' + pub has_%(rs_name)s: bool, +''', + rs_name=rs_name(memb.name, protect=False)) + ret += mcgen(''' + pub %(rs_name)s: %(rs_systype)s, +''', + rs_systype=rs_systype(memb.type.c_type(), ''), rs_name=rs_name(memb.name)) + return ret + + +def gen_rs_sys_free(ty): + return mcgen(''' + +extern "C" { + pub fn qapi_free_%(ty)s(obj: *mut %(ty)s); +} +''', ty=ty) + + +def gen_rs_sys_variants(name, variants): + ret = mcgen(''' + +#[repr(C)] +#[derive(Copy, Clone)] +pub union %(rs_name)s { /* union tag is @%(tag_name)s */ +''', + tag_name=rs_name(variants.tag_member.name), + rs_name=name) + + for var in variants.variants: + if var.ifcond: + raise NotImplementedError("ifcond are not implemented") + if var.type.name == 'q_empty': + continue + ret += mcgen(''' + pub %(rs_name)s: %(rs_systype)s, +''', + rs_systype=rs_systype(var.type.c_unboxed_type(), ''), + rs_name=rs_name(var.name)) + + ret += mcgen(''' +} + +impl ::std::fmt::Debug for %(rs_name)s { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + f.debug_struct(&format!("%(rs_name)s @ {:?}", self as *const _)) + .finish() + } +} +''', rs_name=name) + + return ret + + +def gen_rs_sys_object(name, ifcond, base, members, variants): + if ifcond: + raise NotImplementedError("ifcond are not implemented") + if name in objects_seen: + return '' + + ret = '' + objects_seen.add(name) + unionty = name + 'Union' + if variants: + for v in variants.variants: + if v.ifcond: + raise NotImplementedError("ifcond are not implemented") + if isinstance(v.type, QAPISchemaObjectType): + ret += gen_rs_sys_object(v.type.name, v.type.ifcond, v.type.base, + v.type.local_members, v.type.variants) + ret += gen_rs_sys_variants(unionty, variants) + + ret += gen_rs_sys_free(rs_name(name)) + ret += mcgen(''' + +#[repr(C)] +#[derive(Copy, Clone, Debug)] +pub struct %(rs_name)s { +''', + rs_name=rs_name(name)) + + if base: + if not base.is_implicit(): + ret += mcgen(''' + // Members inherited: +''') + ret += gen_rs_sys_struct_members(base.members) + if not base.is_implicit(): + ret += mcgen(''' + // Own members: +''') + + ret += gen_rs_sys_struct_members(members) + if variants: + ret += mcgen(''' + pub u: %(unionty)s +''', unionty=unionty) + ret += mcgen(''' +} +''') + return ret + + +def gen_rs_sys_variant(name, ifcond, variants): + if ifcond: + raise NotImplementedError("ifcond are not implemented") + if name in objects_seen: + return '' + + objects_seen.add(name) + + vs = '' + for var in variants.variants: + if var.type.name == 'q_empty': + continue + vs += mcgen(''' + pub %(mem_name)s: %(rs_systype)s, +''', + rs_systype=rs_systype(var.type.c_unboxed_type(), ''), + mem_name=rs_name(var.name)) + + return mcgen(''' + +#[repr(C)] +#[derive(Copy,Clone)] +pub union %(rs_name)sUnion { + %(variants)s +} + +impl ::std::fmt::Debug for %(rs_name)sUnion { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + f.debug_struct(&format!("%(rs_name)sUnion @ {:?}", self as *const _)) + .finish() + } +} + +#[repr(C)] +#[derive(Copy,Clone,Debug)] +pub struct %(rs_name)s { + pub ty: QType, + pub u: %(rs_name)sUnion, +} +''', + rs_name=rs_name(name), variants=vs) + + +def gen_rs_sys_array(name, ifcond, element_type): + if ifcond: + raise NotImplementedError("ifcond are not implemented") + ret = mcgen(''' + +#[repr(C)] +#[derive(Copy,Clone)] +pub struct %(rs_name)s { + pub next: *mut %(rs_name)s, + pub value: %(rs_systype)s, +} + +impl ::std::fmt::Debug for %(rs_name)s { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + f.debug_struct(&format!("%(rs_name)s @ {:?}", self as *const _)) + .finish() + } +} +''', + rs_name=rs_name(name), rs_systype=rs_systype(element_type.c_type(), '')) + ret += gen_rs_sys_free(rs_name(name)) + return ret + + +class QAPISchemaGenRsSysTypeVisitor(QAPISchemaRsVisitor): + + def __init__(self, prefix): + super().__init__(prefix, 'qapi-sys-types') + + def visit_begin(self, schema): + # gen_object() is recursive, ensure it doesn't visit the empty type + objects_seen.add(schema.the_empty_object_type.name) + self._gen.preamble_add( + mcgen(''' +// generated by qapi-gen, DO NOT EDIT + +use common::sys::{QNull, QObject}; + +''')) + + def visit_enum_type(self, name, info, ifcond, features, members, prefix): + self._gen.add(gen_rs_sys_enum(name, ifcond, members, prefix)) + + def visit_array_type(self, name, info, ifcond, element_type): + self._gen.add(gen_rs_sys_array(name, ifcond, element_type)) + + def visit_object_type(self, name, info, ifcond, features, + base, members, variants): + if name.startswith('q_'): + return + self._gen.add(gen_rs_sys_object(name, ifcond, base, members, variants)) + + def visit_alternate_type(self, name, info, ifcond, features, variants): + self._gen.add(gen_rs_sys_variant(name, ifcond, variants)) + + +def gen_rs_systypes(schema, output_dir, prefix, opt_builtins): + vis = QAPISchemaGenRsSysTypeVisitor(prefix) + schema.visit(vis) + vis.write(output_dir) From patchwork Sun Oct 11 20:35:06 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 303142 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.5 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 13A04C433E7 for ; Sun, 11 Oct 2020 20:39:12 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id B22572145D for ; Sun, 11 Oct 2020 20:39:11 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="fNKYe3W6" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org B22572145D Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:59876 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kRi7a-0005Lq-N3 for qemu-devel@archiver.kernel.org; Sun, 11 Oct 2020 16:39:10 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:57530) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kRi5F-0001hC-80 for qemu-devel@nongnu.org; Sun, 11 Oct 2020 16:36:45 -0400 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:57777) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1kRi5D-0005WS-JR for qemu-devel@nongnu.org; Sun, 11 Oct 2020 16:36:44 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1602448603; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=egvCJt14G0LEvqg5zPm7LF3yH6IbcZwusrSLXxHeOH0=; b=fNKYe3W6qhBAXV3LJ/AAsbczFD3Xh7cNerTi6e2HUBlTQNueN2vc5UtXyi/+uhUt4bG214 ImC3H94UJU4lzB94khLg5Sbj3krpVljVvMBt1HTeWQj6UiyiaIB1TlVZMwQi9Kih56H90f p6r9LPPJnf6Ca80wtnKxL5uMcQh2TdA= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-333-N9K3a7k0OLuLHCVYud_OxQ-1; Sun, 11 Oct 2020 16:36:40 -0400 X-MC-Unique: N9K3a7k0OLuLHCVYud_OxQ-1 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 75B58107ACF9 for ; Sun, 11 Oct 2020 20:36:39 +0000 (UTC) Received: from localhost (unknown [10.36.110.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id 418DA5DA30; Sun, 11 Oct 2020 20:36:32 +0000 (UTC) From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Subject: [PoCv2 08/15] qga/rust: generate QGA QAPI sys bindings Date: Mon, 12 Oct 2020 00:35:06 +0400 Message-Id: <20201011203513.1621355-9-marcandre.lureau@redhat.com> In-Reply-To: <20201011203513.1621355-1-marcandre.lureau@redhat.com> References: <20201011203513.1621355-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=marcandre.lureau@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=216.205.24.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/10/11 16:35:36 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=-0.01, RCVD_IN_MSPIKE_WL=-0.01, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: pbonzini@redhat.com, berrange@redhat.com, armbru@redhat.com, stefanha@redhat.com, =?utf-8?q?Marc-Andr=C3=A9_Lureau?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Marc-André Lureau Use qapi-gen to generate low-level C sys bindings for QAPI types, include them to the build. Signed-off-by: Marc-André Lureau --- qga/Cargo.toml | 4 ++++ qga/lib.rs | 1 + qga/meson.build | 11 +++++++++++ qga/qapi_sys.rs | 5 +++++ 4 files changed, 21 insertions(+) create mode 100644 qga/qapi_sys.rs diff --git a/qga/Cargo.toml b/qga/Cargo.toml index 50c3415ab2..9966057594 100644 --- a/qga/Cargo.toml +++ b/qga/Cargo.toml @@ -4,6 +4,10 @@ version = "0.1.0" edition = "2018" license = "GPLv2" +[dependencies] +common = { path = "../rust/common" } +libc = "^0.2.76" + [lib] path = "lib.rs" crate-type = ["staticlib"] diff --git a/qga/lib.rs b/qga/lib.rs index e69de29bb2..050a47e2a3 100644 --- a/qga/lib.rs +++ b/qga/lib.rs @@ -0,0 +1 @@ +mod qapi_sys; diff --git a/qga/meson.build b/qga/meson.build index 62e13a11b3..dbc8f1623b 100644 --- a/qga/meson.build +++ b/qga/meson.build @@ -47,10 +47,21 @@ qga_ss = qga_ss.apply(config_host, strict: false) qga_rs = declare_dependency() if with_rust + qga_qapi_rs_outputs = [ + 'qga-qapi-sys-types.rs', + ] + + qapi_gen_rs_files = custom_target('QGA QAPI Rust bindings', + output: qga_qapi_rs_outputs, + input: 'qapi-schema.json', + command: [ qapi_gen, '-r', '-o', 'qga', '-p', 'qga-', '@INPUT0@' ], + depend_files: qapi_gen_depends) + cargo_qga = custom_target('cargo-qga', build_by_default: true, output: ['libqga.args', 'libqga.a'], build_always_stale: true, + depends: [qapi_gen_rs_files], command: [cargo_wrapper, 'build-lib', meson.current_build_dir(), diff --git a/qga/qapi_sys.rs b/qga/qapi_sys.rs new file mode 100644 index 0000000000..06fc49b826 --- /dev/null +++ b/qga/qapi_sys.rs @@ -0,0 +1,5 @@ +#![allow(dead_code)] +include!(concat!( + env!("MESON_BUILD_ROOT"), + "/qga/qga-qapi-sys-types.rs" +)); From patchwork Sun Oct 11 20:35:07 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 271544 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.5 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 36C21C433E7 for ; Sun, 11 Oct 2020 20:44:02 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 6D58A20578 for ; Sun, 11 Oct 2020 20:44:01 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="XCPIuZoI" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 6D58A20578 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:46064 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kRiCG-0003U1-H4 for qemu-devel@archiver.kernel.org; Sun, 11 Oct 2020 16:44:00 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:57576) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kRi5R-0001oZ-9E for qemu-devel@nongnu.org; Sun, 11 Oct 2020 16:36:57 -0400 Received: from us-smtp-delivery-124.mimecast.com ([63.128.21.124]:32448) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1kRi5O-0005XF-KA for qemu-devel@nongnu.org; Sun, 11 Oct 2020 16:36:56 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1602448613; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=HYWZkMKWHLktsWqLRuW6+7g2bKU6rV7ednfYnjWHwEY=; b=XCPIuZoIn15R/aYGSpqsiiF09wZzIcaLySGz19Gzu12bvjovCfwTF0CqXNPSWkaBSCTc5A +TnufGqGMGstW2HM9V/KbPYbhg5278/KtJB3mBR/ikaU2QOFH19xFdX0+C5xhSFLyC1SgO JeHeIeiFMjkBXjfiSUFAbqXL/7UatC8= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-462-TQEGmjTcPP6s_u58-mq1Hg-1; Sun, 11 Oct 2020 16:36:51 -0400 X-MC-Unique: TQEGmjTcPP6s_u58-mq1Hg-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 7CB1110066FE for ; Sun, 11 Oct 2020 20:36:50 +0000 (UTC) Received: from localhost (unknown [10.36.110.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id 4F2B660C05; Sun, 11 Oct 2020 20:36:42 +0000 (UTC) From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Subject: [PoCv2 09/15] scripts/qapi: add generation of Rust bindings for types Date: Mon, 12 Oct 2020 00:35:07 +0400 Message-Id: <20201011203513.1621355-10-marcandre.lureau@redhat.com> In-Reply-To: <20201011203513.1621355-1-marcandre.lureau@redhat.com> References: <20201011203513.1621355-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=marcandre.lureau@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=63.128.21.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/10/11 16:23:51 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -30 X-Spam_score: -3.1 X-Spam_bar: --- X-Spam_report: (-3.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=-1, RCVD_IN_MSPIKE_WL=-0.01, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: pbonzini@redhat.com, berrange@redhat.com, armbru@redhat.com, stefanha@redhat.com, =?utf-8?q?Marc-Andr=C3=A9_Lureau?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Marc-André Lureau Generate high-level idiomatic Rust code for the QAPI types, with to/from translations for C FFI. - no conditional support yet - C FFI types are mapped to higher-level types (char*->String, Foo*->Foo, has_foo/foo->Option etc) - C enums are simply aliased - C structures have corresponding Rust structures - alternate are represented as Rust enum (TODO: to/from conversion) - variants A are represented as Rust AEnum enums. A AEnum::kind() method allows to easily get the variant C kind enum value. The translation code also uses a helper enum ACEnum to hold the C pointer variant. There might be better ways to achieve the translation, but that one works for now. - unions are represented in a similar way as C, as a struct S with a "u" member (since S may have extra 'base' fields). However, the discriminant isn't a member of S, as Rust enum variant don't need that. - lists are represented as Vec and translated thanks to vec_to/from translate macros Signed-off-by: Marc-André Lureau --- meson.build | 1 + scripts/qapi-gen.py | 2 + scripts/qapi/rs.py | 78 +++++++ scripts/qapi/rs_types.py | 447 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 528 insertions(+) create mode 100644 scripts/qapi/rs_types.py diff --git a/meson.build b/meson.build index b6b8330b97..666e38033e 100644 --- a/meson.build +++ b/meson.build @@ -1149,6 +1149,7 @@ qapi_gen_depends = [ meson.source_root() / 'scripts/qapi/__init__.py', meson.source_root() / 'scripts/qapi/common.py', meson.source_root() / 'scripts/qapi/rs.py', meson.source_root() / 'scripts/qapi/rs_sys.py', + meson.source_root() / 'scripts/qapi/rs_types.py', meson.source_root() / 'scripts/qapi-gen.py', ] diff --git a/scripts/qapi-gen.py b/scripts/qapi-gen.py index 5bfe9c8cd1..556bfe9e7b 100644 --- a/scripts/qapi-gen.py +++ b/scripts/qapi-gen.py @@ -17,6 +17,7 @@ from qapi.types import gen_types from qapi.visit import gen_visit from qapi.rs_sys import gen_rs_systypes +from qapi.rs_types import gen_rs_types def main(argv): parser = argparse.ArgumentParser( @@ -50,6 +51,7 @@ def main(argv): if args.rust: gen_rs_systypes(schema, args.output_dir, args.prefix, args.builtins) + gen_rs_types(schema, args.output_dir, args.prefix, args.builtins) else: gen_types(schema, args.output_dir, args.prefix, args.builtins) gen_visit(schema, args.output_dir, args.prefix, args.builtins) diff --git a/scripts/qapi/rs.py b/scripts/qapi/rs.py index daa946580b..cab5bb9b72 100644 --- a/scripts/qapi/rs.py +++ b/scripts/qapi/rs.py @@ -11,6 +11,8 @@ from qapi.common import * from qapi.gen import QAPIGen, QAPISchemaVisitor +rs_lists = set() + rs_name_trans = str.maketrans('.-', '__') # Map @name to a valid Rust identifier. @@ -42,12 +44,55 @@ def rs_name(name, protect=True): return name +def rs_type(c_type, ns='qapi::', optional=False): + vec = False + to_rs = { + 'char': 'i8', + 'int8_t': 'i8', + 'uint8_t': 'u8', + 'int16_t': 'i16', + 'uint16_t': 'u16', + 'int32_t': 'i32', + 'uint32_t': 'u32', + 'int64_t': 'i64', + 'uint64_t': 'u64', + 'double': 'f64', + 'bool': 'bool', + 'str': 'String', + } + if c_type.startswith('const '): + c_type = c_type[6:] + if c_type.endswith(pointer_suffix): + c_type = c_type.rstrip(pointer_suffix).strip() + if c_type.endswith('List'): + c_type = c_type[:-4] + vec = True + else: + to_rs = { + 'char': 'String', + } + + if c_type in to_rs: + ret = to_rs[c_type] + else: + ret = ns + c_type + + if vec: + ret = 'Vec<%s>' % ret + if optional: + return 'Option<%s>' % ret + else: + return ret + + def rs_ctype_parse(c_type): is_pointer = False if c_type.endswith(pointer_suffix): is_pointer = True c_type = c_type.rstrip(pointer_suffix).strip() is_list = c_type.endswith('List') + if is_list: + rs_lists.add(c_type) is_const = False if c_type.startswith('const '): is_const = True @@ -103,6 +148,39 @@ def to_camel_case(value): return value +def to_qemu_none(c_type, name): + (is_pointer, _, is_list, _) = rs_ctype_parse(c_type) + + if is_pointer: + if c_type == 'char': + return mcgen(''' + let %(name)s_ = CString::new(%(name)s).unwrap(); + let %(name)s = %(name)s_.as_ptr(); +''', name=name) + elif is_list: + return mcgen(''' + let %(name)s_ = NewPtr(%(name)s).to_qemu_none(); + let %(name)s = %(name)s_.0.0; +''', name=name) + else: + return mcgen(''' + let %(name)s_ = %(name)s.to_qemu_none(); + let %(name)s = %(name)s_.0; +''', name=name) + return '' + + +def from_qemu(var_name, c_type, full=False): + (is_pointer, _, is_list, _) = rs_ctype_parse(c_type) + ptr = '{} as *{} _'.format(var_name, 'mut' if full else 'const') + if is_list: + ptr = 'NewPtr({})'.format(ptr) + if is_pointer: + return 'from_qemu_{}({})'.format('full' if full else 'none', ptr) + else: + return var_name + + class QAPIGenRs(QAPIGen): def __init__(self, fname): diff --git a/scripts/qapi/rs_types.py b/scripts/qapi/rs_types.py new file mode 100644 index 0000000000..3a7d8914c8 --- /dev/null +++ b/scripts/qapi/rs_types.py @@ -0,0 +1,447 @@ +# This work is licensed under the terms of the GNU GPL, version 2. +# See the COPYING file in the top-level directory. +""" +QAPI Rust types generator +""" + +from qapi.common import * +from qapi.rs import * + + +objects_seen = set() + + +def gen_rs_variants_enum_kind(name, kind_arms): + return mcgen(''' + +impl %(rs_name)sEnum { + pub fn kind(&self) -> %(rs_name)sKind { + match self { + %(kind_arms)s + } + } +} +''', rs_name=rs_name(name), kind_arms=kind_arms) + + +def gen_rs_variants_to_qemu(name, variants): + ret = mcgen(''' + +pub enum %(rs_name)sCEnum<'a> { +''', rs_name=rs_name(name)) + + none_arms = '' + full_arms = '' + for var in variants.variants: + var_name = to_camel_case(rs_name(var.name, False)) + type_name = var.type.name + if type_name == 'q_empty': + continue + if type_name.endswith('-wrapper'): + type_name = type_name[6:-8] + ret += mcgen(''' + %(var_name)s(<%(rs_type)s as ToQemuPtr<'a, *mut %(rs_systype)s>>::Storage), +''', var_name=var_name, rs_type=rs_type(type_name, ''), rs_systype=rs_systype(type_name)) + none_arms += mcgen(''' + %(rs_name)sEnum::%(var_name)s(v) => { + let stash_ = v.to_qemu_none(); + (stash_.0 as *mut std::ffi::c_void, %(rs_name)sCEnum::%(var_name)s(stash_.1)) + }, +''', rs_name=rs_name(name), var_name=var_name) + full_arms += mcgen(''' + %(rs_name)sEnum::%(var_name)s(v) => { + let ptr = v.to_qemu_full(); + ptr as *mut std::ffi::c_void + }, +''', rs_name=rs_name(name), var_name=var_name) + + ret += mcgen(''' +} + +impl QemuPtrDefault for %(rs_name)sEnum { + type QemuType = *mut std::ffi::c_void; +} + +impl<'a> ToQemuPtr<'a, *mut std::ffi::c_void> for %(rs_name)sEnum { + type Storage = %(rs_name)sCEnum<'a>; + + #[inline] + fn to_qemu_none(&'a self) -> Stash<'a, *mut std::ffi::c_void, %(rs_name)sEnum> { + let (ptr_, cenum_) = match self { + %(none_arms)s + }; + + Stash(ptr_, cenum_) + } + + #[inline] + fn to_qemu_full(&self) -> *mut std::ffi::c_void { + match self { + %(full_arms)s + } + } +} +''', rs_name=rs_name(name), none_arms=none_arms, full_arms=full_arms) + return ret + + +def gen_rs_variants(name, variants): + ret = mcgen(''' + +#[derive(Clone,Debug)] +pub enum %(rs_name)sEnum { +''', rs_name=rs_name(name)) + + kind_arms = '' + for var in variants.variants: + if var.ifcond: + raise NotImplementedError("ifcond are not implemented") + type_name = var.type.name + var_name = to_camel_case(rs_name(var.name, False)) + if type_name == 'q_empty': + continue + if type_name.endswith('-wrapper'): + type_name = type_name[6:-8] # remove q_obj*-wrapper + kind_arms += mcgen(''' + Self::%(var_name)s(_) => { %(rs_name)sKind::%(var_name)s }, +''', var_name=var_name, rs_name=rs_name(name)) + ret += mcgen(''' + %(var_name)s(%(rs_type)s), +''', var_name=var_name, rs_type=rs_type(type_name, '')) + + ret += mcgen(''' +} +''') + + ret += gen_rs_variants_enum_kind(name, kind_arms) + ret += gen_rs_variants_to_qemu(name, variants) + # TODO FromQemu + return ret + + +def gen_rs_object_to_qemu(name, base, members, variants): + storage = [] + stash = [] + sys_memb = [] + memb_none = '' + memb_full = '' + for memb in members: + memb_name = rs_name(memb.name) + c_type = memb.type.c_type() + (is_pointer, _, is_list, _) = rs_ctype_parse(c_type) + if is_pointer: + t = rs_type(memb.type.c_type(), optional=memb.optional, ns='') + p = rs_systype(memb.type.c_type(), list_as_newp=True) + s = "Stash<'a, %s, %s>" % (p, t) + storage.append(s) + if memb.optional: + has_memb_name = 'has_%s' % rs_name(memb.name, protect=False) + sys_memb.append(has_memb_name) + has_memb = mcgen(''' + let %(has_memb_name)s = self.%(memb_name)s.is_some(); +''', memb_name=memb_name, has_memb_name=has_memb_name) + memb_none += has_memb + memb_full += has_memb + + if is_pointer: + stash_name = '{}_stash_'.format(memb_name) + stash.append(stash_name) + var = 'NewPtr({})'.format(memb_name) if is_list else memb_name + memb_none += mcgen(''' + let %(stash_name)s = self.%(memb_name)s.to_qemu_none(); + let %(var)s = %(stash_name)s.0; +''', stash_name=stash_name, memb_name=memb_name, var=var) + memb_full += mcgen(''' + let %(var)s = self.%(memb_name)s.to_qemu_full(); +''', memb_name=memb_name, var=var) + else: + unwrap = '' + if memb.optional: + unwrap = '.unwrap_or_default()' + memb = mcgen(''' + let %(memb_name)s = self.%(memb_name)s%(unwrap)s; +''', memb_name=memb_name, unwrap=unwrap) + memb_none += memb + memb_full += memb + + sys_memb.append(memb_name) + + if variants: + tag_name = rs_name(variants.tag_member.name) + sys_memb.append(tag_name) + sys_memb.append('u') + p = '*mut std::ffi::c_void' + s = "Stash<'a, %s, %sEnum>" % (p, name) + storage.append(s) + tag = mcgen(''' + let %(tag_name)s = self.u.kind(); +''', sys=rs_systype(name), tag_name=tag_name) + memb_none += tag + memb_full += tag + arms = '' + for var in variants.variants: + if var.type.name == 'q_empty': + continue + arms += mcgen('%(rs_name)sEnum::%(kind_name)s(_) => qapi_sys::%(rs_name)sUnion { %(var_name)s: %(var_type)s { data: u_ptr_ as *mut _ } },', + rs_name=rs_name(name), kind_name=to_camel_case(var.name), var_name=rs_name(var.name), var_type=rs_systype(var.type.c_name())) + memb_none += mcgen(''' + let u_stash_ = self.u.to_qemu_none(); + let u_ptr_ = u_stash_.0; + let u = match self.u { + %(arms)s + }; +''', arms=arms) + stash.append('u_stash_') + memb_full += mcgen(''' + let u_ptr_ = self.u.to_qemu_full(); + let u = match self.u { + %(arms)s + }; +''', arms=arms) + + return mcgen(''' + +impl QemuPtrDefault for %(rs_name)s { + type QemuType = *mut qapi_sys::%(rs_name)s; +} + +impl<'a> ToQemuPtr<'a, *mut qapi_sys::%(rs_name)s> for %(rs_name)s { + type Storage = (Box, %(storage)s); + + #[inline] + fn to_qemu_none(&'a self) -> Stash<'a, *mut qapi_sys::%(rs_name)s, %(rs_name)s> { + %(memb_none)s + let mut box_ = Box::new(qapi_sys::%(rs_name)s { %(sys_memb)s }); + + Stash(&mut *box_, (box_, %(stash)s)) + } + + #[inline] + fn to_qemu_full(&self) -> *mut qapi_sys::%(rs_name)s { + unsafe { + %(memb_full)s + let ptr = sys::g_malloc0(std::mem::size_of::<*const %(rs_name)s>()) as *mut _; + *ptr = qapi_sys::%(rs_name)s { %(sys_memb)s }; + ptr + } + } +} +''', + rs_name=rs_name(name), storage=', '.join(storage), + sys_memb=', '.join(sys_memb), memb_none=memb_none, memb_full=memb_full, stash=', '.join(stash)) + + +def gen_rs_object_from_qemu(name, base, members, variants): + memb_names = [] + if base: + memb_names.extend([rs_name(memb.name) for memb in base.members]) + memb_names.extend([rs_name(memb.name) for memb in members]) + + ret = mcgen(''' +} + +impl FromQemuPtrFull<*mut qapi_sys::%(rs_name)s> for %(rs_name)s { + unsafe fn from_qemu_full(sys: *mut qapi_sys::%(rs_name)s) -> Self { + let ret = from_qemu_none(sys as *const _); + qapi_sys::qapi_free_%(rs_name)s(sys); + ret + } +} + +impl FromQemuPtrNone<*const qapi_sys::%(rs_name)s> for %(rs_name)s { + unsafe fn from_qemu_none(sys: *const qapi_sys::%(rs_name)s) -> Self { + let sys = & *sys; +''', rs_name=rs_name(name)) + + for memb in members: + memb_name = rs_name(memb.name) + val = from_qemu('sys.' + memb_name, memb.type.c_type()) + if memb.optional: + val = mcgen('''{ + if sys.has_%(memb_name)s { + Some(%(val)s) + } else { + None + } +}''', memb_name=rs_name(memb.name, protect=False), val=val) + + ret += mcgen(''' + let %(memb_name)s = %(val)s; +''', memb_name=memb_name, val=val) + + if variants: + arms = '' + for variant in variants.tag_member.type.member_names(): + arms += mcgen(''' + %(enum)s::%(variant)s => { %(rs_name)sEnum::%(variant)s(from_qemu_none(sys.u.%(memb)s.data as *const _)) }, +''', enum=variants.tag_member.type.name, memb=rs_name(variant), + variant=to_camel_case(variant), rs_name=rs_name(name)) + ret += mcgen(''' + let u = match sys.%(tag)s { + %(arms)s + _ => panic!("Variant with invalid tag"), + }; +''', tag=rs_name(variants.tag_member.name), arms=arms) + memb_names.append('u') + + ret += mcgen(''' + Self { %(memb_names)s } + } +} +''', rs_name=rs_name(name), memb_names=', '.join(memb_names)) + return ret + + +def gen_struct_members(members): + ret = '' + for memb in members: + if memb.ifcond: + raise NotImplementedError("ifcond are not implemented") + rsname = rs_name(memb.name) + ret += mcgen(''' + pub %(rs_name)s: %(rs_type)s, +''', + rs_type=rs_type(memb.type.c_type(), '', optional=memb.optional), rs_name=rsname) + return ret + + +def gen_rs_object(name, base, members, variants): + if name in objects_seen: + return '' + + if variants: + members = [m for m in members if m.name != variants.tag_member.name] + + ret = '' + objects_seen.add(name) + + if variants: + ret += gen_rs_variants(name, variants) + + ret += mcgen(''' + +#[derive(Clone, Debug)] +pub struct %(rs_name)s { +''', + rs_name=rs_name(name)) + + if base: + if not base.is_implicit(): + ret += mcgen(''' + // Members inherited: +''', + c_name=base.c_name()) + ret += gen_struct_members(base.members) + if not base.is_implicit(): + ret += mcgen(''' + // Own members: +''') + + ret += gen_struct_members(members) + + if variants: + ret += mcgen(''' + pub u: %(rs_type)sEnum, +''', rs_type=name) + + ret += gen_rs_object_from_qemu(name, base, members, variants) + ret += gen_rs_object_to_qemu(name, base, members, variants) + return ret + + +def gen_rs_alternate(name, variants): + if name in objects_seen: + return '' + + ret = '' + objects_seen.add(name) + + ret += mcgen(''' + +#[derive(Clone,Debug)] +pub enum %(rs_name)s { +''', + rs_name=rs_name(name)) + + for var in variants.variants: + if var.ifcond: + raise NotImplementedError("ifcond are not implemented") + if var.type.name == 'q_empty': + continue + ret += mcgen(''' + %(mem_name)s(%(rs_type)s), +''', + rs_type=rs_type(var.type.c_unboxed_type(), ''), + mem_name=to_camel_case(rs_name(var.name))) + ret += mcgen(''' +} +''') + # TODO: add to/from conversion + return ret + + +def gen_rs_enum(name): + return mcgen(''' + +pub type %(rs_name)s = qapi_sys::%(rs_name)s; +''', rs_name=rs_name(name)) + + +class QAPISchemaGenRsTypeVisitor(QAPISchemaRsVisitor): + + def __init__(self, prefix): + super().__init__(prefix, 'qapi-types') + + def visit_begin(self, schema): + # gen_object() is recursive, ensure it doesn't visit the empty type + objects_seen.add(schema.the_empty_object_type.name) + self._gen.preamble_add( + mcgen(''' +// generated by qapi-gen, DO NOT EDIT + +use crate::qapi_sys; + +''')) + + def visit_end(self): + for name in rs_lists: + self._gen.add(mcgen(''' + +vec_from_qemu!(%(rs)s, %(sys)s, qapi_free_%(sys)s); +vec_to_qemu!(%(rs)s, %(sys)s); +''', sys=name, rs=name[:-4])) + + def visit_command(self, name, info, ifcond, features, + arg_type, ret_type, gen, success_response, boxed, + allow_oob, allow_preconfig, coroutine): + if ifcond: + raise NotImplementedError("ifcond are not implemented") + if not gen: + return + # call from_qemu() to eventually register a list + if ret_type: + from_qemu('', ret_type.c_type()) + + def visit_object_type(self, name, info, ifcond, features, + base, members, variants): + if ifcond: + raise NotImplementedError("ifcond are not implemented") + if name.startswith('q_'): + return + self._gen.add(gen_rs_object(name, base, members, variants)) + + def visit_enum_type(self, name, info, ifcond, features, members, prefix): + if ifcond: + raise NotImplementedError("ifcond are not implemented") + self._gen.add(gen_rs_enum(name)) + + def visit_alternate_type(self, name, info, ifcond, features, variants): + if ifcond: + raise NotImplementedError("ifcond are not implemented") + self._gen.add(gen_rs_alternate(name, variants)) + + +def gen_rs_types(schema, output_dir, prefix, opt_builtins): + vis = QAPISchemaGenRsTypeVisitor(prefix) + schema.visit(vis) + vis.write(output_dir) From patchwork Sun Oct 11 20:35:08 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 271545 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.5 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1362DC433DF for ; Sun, 11 Oct 2020 20:41:26 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id A91CA207FB for ; Sun, 11 Oct 2020 20:41:25 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="NfInWK1b" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org A91CA207FB Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:40070 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kRi9k-0000hZ-QU for qemu-devel@archiver.kernel.org; Sun, 11 Oct 2020 16:41:24 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:57660) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kRi5b-0001sq-L6 for qemu-devel@nongnu.org; Sun, 11 Oct 2020 16:37:08 -0400 Received: from us-smtp-delivery-124.mimecast.com ([63.128.21.124]:54990) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1kRi5Z-0005Xk-Vl for qemu-devel@nongnu.org; Sun, 11 Oct 2020 16:37:07 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1602448624; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=69CoiKyBWo9QUtUgrmlNSSXEFQ/HwyM1UPy3Ni4+k5o=; b=NfInWK1bam9QojfNajg3sJMDbKwHKUwr6lo6I/EvbaK2X8e8zWIa9ouurNPSad0ZHaDZ8s ZxT+R35i+PMeqkM79AQK9ZBM4bBjEXbgPJyH9NMiSsRIjEgffFWWgPdJ5Vqpkno4A5XT0S LGwGWh40P4rM2smraTo9Q0J4cAkT3uA= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-318-6spTaWbmOBi5GRZj5l5xsw-1; Sun, 11 Oct 2020 16:37:01 -0400 X-MC-Unique: 6spTaWbmOBi5GRZj5l5xsw-1 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id E3F4B107ACF5 for ; Sun, 11 Oct 2020 20:37:00 +0000 (UTC) Received: from localhost (unknown [10.36.110.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id 4C5097512E; Sun, 11 Oct 2020 20:36:53 +0000 (UTC) From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Subject: [PoCv2 10/15] qga/rust: build Rust types Date: Mon, 12 Oct 2020 00:35:08 +0400 Message-Id: <20201011203513.1621355-11-marcandre.lureau@redhat.com> In-Reply-To: <20201011203513.1621355-1-marcandre.lureau@redhat.com> References: <20201011203513.1621355-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=marcandre.lureau@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=63.128.21.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/10/11 16:23:51 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -30 X-Spam_score: -3.1 X-Spam_bar: --- X-Spam_report: (-3.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=-1, RCVD_IN_MSPIKE_WL=-0.01, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: pbonzini@redhat.com, berrange@redhat.com, armbru@redhat.com, stefanha@redhat.com, =?utf-8?q?Marc-Andr=C3=A9_Lureau?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Marc-André Lureau Signed-off-by: Marc-André Lureau --- qga/lib.rs | 1 + qga/meson.build | 1 + qga/qapi.rs | 6 ++++++ 3 files changed, 8 insertions(+) create mode 100644 qga/qapi.rs diff --git a/qga/lib.rs b/qga/lib.rs index 050a47e2a3..bff4107569 100644 --- a/qga/lib.rs +++ b/qga/lib.rs @@ -1 +1,2 @@ +mod qapi; mod qapi_sys; diff --git a/qga/meson.build b/qga/meson.build index dbc8f1623b..aedbd07a04 100644 --- a/qga/meson.build +++ b/qga/meson.build @@ -49,6 +49,7 @@ qga_rs = declare_dependency() if with_rust qga_qapi_rs_outputs = [ 'qga-qapi-sys-types.rs', + 'qga-qapi-types.rs', ] qapi_gen_rs_files = custom_target('QGA QAPI Rust bindings', diff --git a/qga/qapi.rs b/qga/qapi.rs new file mode 100644 index 0000000000..e4b9113300 --- /dev/null +++ b/qga/qapi.rs @@ -0,0 +1,6 @@ +#![allow(dead_code)] +use common::*; + +new_ptr!(); + +include!(concat!(env!("MESON_BUILD_ROOT"), "/qga/qga-qapi-types.rs")); From patchwork Sun Oct 11 20:35:09 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 303139 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.5 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 71CF4C433DF for ; Sun, 11 Oct 2020 20:44:52 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id E764C20578 for ; Sun, 11 Oct 2020 20:44:51 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="I7X17C6s" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org E764C20578 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:48304 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kRiD5-0004RE-1H for qemu-devel@archiver.kernel.org; Sun, 11 Oct 2020 16:44:51 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:57750) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kRi5k-00027Z-BI for qemu-devel@nongnu.org; Sun, 11 Oct 2020 16:37:16 -0400 Received: from us-smtp-delivery-124.mimecast.com ([63.128.21.124]:46907) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1kRi5i-0005ZP-M0 for qemu-devel@nongnu.org; Sun, 11 Oct 2020 16:37:15 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1602448633; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=XlKLzn5XQx+MgQAM4EHXhVcJekM1LfEac+tlMU7Ov/E=; b=I7X17C6smd4vtpBWPnXTsTPr40hZyxZAltHebzhRwc0/t7GQy+HMuvHFNyJrHX+y9e/b+X ood9S8O8HbFDEEs0L0nmznNB08yU+ajQZewFc87KoAIwyoCVKtmnh6M1gl7oc4ON7z1xkD b2fr9diMJt4sUoCpBIXZ+sOZWqbRTOk= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-100-tbs0h5hQO9S8vGCEgpbzTg-1; Sun, 11 Oct 2020 16:37:12 -0400 X-MC-Unique: tbs0h5hQO9S8vGCEgpbzTg-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 42468802B4A for ; Sun, 11 Oct 2020 20:37:11 +0000 (UTC) Received: from localhost (unknown [10.36.110.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id EC5B660C05; Sun, 11 Oct 2020 20:37:04 +0000 (UTC) From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Subject: [PoCv2 11/15] qga: add qmp! macro helper Date: Mon, 12 Oct 2020 00:35:09 +0400 Message-Id: <20201011203513.1621355-12-marcandre.lureau@redhat.com> In-Reply-To: <20201011203513.1621355-1-marcandre.lureau@redhat.com> References: <20201011203513.1621355-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=marcandre.lureau@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=63.128.21.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/10/11 16:23:51 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -30 X-Spam_score: -3.1 X-Spam_bar: --- X-Spam_report: (-3.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=-1, RCVD_IN_MSPIKE_WL=-0.01, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: pbonzini@redhat.com, berrange@redhat.com, armbru@redhat.com, stefanha@redhat.com, =?utf-8?q?Marc-Andr=C3=A9_Lureau?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Marc-André Lureau Add a macro to help wrapping higher-level qmp handlers, by taking care of errors and return value pointer translation. Signed-off-by: Marc-André Lureau --- qga/lib.rs | 1 + qga/qmp/mod.rs | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 qga/qmp/mod.rs diff --git a/qga/lib.rs b/qga/lib.rs index bff4107569..5fe08c25a3 100644 --- a/qga/lib.rs +++ b/qga/lib.rs @@ -1,2 +1,3 @@ mod qapi; mod qapi_sys; +mod qmp; diff --git a/qga/qmp/mod.rs b/qga/qmp/mod.rs new file mode 100644 index 0000000000..38060100af --- /dev/null +++ b/qga/qmp/mod.rs @@ -0,0 +1,36 @@ +use common::*; + +use crate::*; + +macro_rules! qmp { + // the basic return value variant + ($e:expr, $errp:ident, $errval:expr) => {{ + assert!(!$errp.is_null()); + unsafe { + *$errp = std::ptr::null_mut(); + } + + match $e { + Ok(val) => val, + Err(err) => unsafe { + *$errp = err.to_qemu_full(); + $errval + }, + } + }}; + // the ptr return value variant + ($e:expr, $errp:ident) => {{ + assert!(!$errp.is_null()); + unsafe { + *$errp = std::ptr::null_mut(); + } + + match $e { + Ok(val) => val.to_qemu_full().into(), + Err(err) => unsafe { + *$errp = err.to_qemu_full(); + std::ptr::null_mut() + }, + } + }}; +} From patchwork Sun Oct 11 20:35:10 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 271542 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-14.5 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, MENTIONS_GIT_HOSTING, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 60C62C433DF for ; Sun, 11 Oct 2020 20:48:11 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 03C1E20678 for ; Sun, 11 Oct 2020 20:48:10 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="KWw6Uay2" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 03C1E20678 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:56676 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kRiGH-00083J-VP for qemu-devel@archiver.kernel.org; Sun, 11 Oct 2020 16:48:09 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:57802) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kRi5y-0002G6-Tt for qemu-devel@nongnu.org; Sun, 11 Oct 2020 16:37:32 -0400 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:31717) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1kRi5u-0005Zv-Jg for qemu-devel@nongnu.org; Sun, 11 Oct 2020 16:37:30 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1602448646; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=tMbEFUjxPSyAU3nqy9BsI64+jEiY61NYPw2mnJQxISc=; b=KWw6Uay2My7yAixoM1SOKpKd2V70FvVQ+xL8JbUnY9dof3y1JSIqvj+oM/Krptcv41XWgL 4wQg4DFHs26k+phDPj8lFa9ClDbkOAOLDHvo5/WMWN2hEKnpKc2fJEm7djlLTmKxIBoZgY B19EGckYxFvR6ye4S8GliNv9uuVllrM= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-355-zhsTWrE0OyuzUIeZtOWrHg-1; Sun, 11 Oct 2020 16:37:22 -0400 X-MC-Unique: zhsTWrE0OyuzUIeZtOWrHg-1 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id D5617802B4A for ; Sun, 11 Oct 2020 20:37:21 +0000 (UTC) Received: from localhost (unknown [10.36.110.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id CD9771A8EC; Sun, 11 Oct 2020 20:37:14 +0000 (UTC) From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Subject: [PoCv2 12/15] qga: implement get-host-name in Rust Date: Mon, 12 Oct 2020 00:35:10 +0400 Message-Id: <20201011203513.1621355-13-marcandre.lureau@redhat.com> In-Reply-To: <20201011203513.1621355-1-marcandre.lureau@redhat.com> References: <20201011203513.1621355-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=marcandre.lureau@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=216.205.24.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/10/11 16:35:36 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=-0.01, RCVD_IN_MSPIKE_WL=-0.01, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: pbonzini@redhat.com, berrange@redhat.com, armbru@redhat.com, stefanha@redhat.com, =?utf-8?q?Marc-Andr=C3=A9_Lureau?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Marc-André Lureau Use the "hostname" crate (https://github.com/svartalf/hostname) (notice the wrong error message in our win32 implementation) Signed-off-by: Marc-André Lureau --- include/qemu/osdep.h | 10 ---------- qga/Cargo.toml | 1 + qga/commands.c | 20 ++++---------------- qga/lib.rs | 2 ++ qga/qmp/hostname.rs | 9 +++++++++ qga/qmp/mod.rs | 7 +++++++ tests/test-qga.c | 2 ++ util/oslib-posix.c | 35 ----------------------------------- util/oslib-win32.c | 13 ------------- 9 files changed, 25 insertions(+), 74 deletions(-) create mode 100644 qga/qmp/hostname.rs diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h index f9ec8c84e9..1ea244fc06 100644 --- a/include/qemu/osdep.h +++ b/include/qemu/osdep.h @@ -664,16 +664,6 @@ static inline void qemu_reset_optind(void) #endif } -/** - * qemu_get_host_name: - * @errp: Error object - * - * Operating system agnostic way of querying host name. - * - * Returns allocated hostname (caller should free), NULL on failure. - */ -char *qemu_get_host_name(Error **errp); - /** * qemu_get_host_physmem: * diff --git a/qga/Cargo.toml b/qga/Cargo.toml index 9966057594..63a419255d 100644 --- a/qga/Cargo.toml +++ b/qga/Cargo.toml @@ -7,6 +7,7 @@ license = "GPLv2" [dependencies] common = { path = "../rust/common" } libc = "^0.2.76" +hostname = "^0.3.1" [lib] path = "lib.rs" diff --git a/qga/commands.c b/qga/commands.c index 3dcd5fbe5c..15478a16e7 100644 --- a/qga/commands.c +++ b/qga/commands.c @@ -512,25 +512,13 @@ int ga_parse_whence(GuestFileWhence *whence, Error **errp) return -1; } +#ifndef CONFIG_WITH_RUST GuestHostName *qmp_guest_get_host_name(Error **errp) { - GuestHostName *result = NULL; - g_autofree char *hostname = qemu_get_host_name(errp); - - /* - * We want to avoid using g_get_host_name() because that - * caches the result and we wouldn't reflect changes in the - * host name. - */ - - if (!hostname) { - hostname = g_strdup("localhost"); - } - - result = g_new0(GuestHostName, 1); - result->host_name = g_steal_pointer(&hostname); - return result; + error_setg(errp, QERR_UNSUPPORTED); + return NULL; } +#endif GuestTimezone *qmp_guest_get_timezone(Error **errp) { diff --git a/qga/lib.rs b/qga/lib.rs index 5fe08c25a3..f4967f59e5 100644 --- a/qga/lib.rs +++ b/qga/lib.rs @@ -1,3 +1,5 @@ +pub use common::{err, Error, Result}; + mod qapi; mod qapi_sys; mod qmp; diff --git a/qga/qmp/hostname.rs b/qga/qmp/hostname.rs new file mode 100644 index 0000000000..c3eb1f6fd2 --- /dev/null +++ b/qga/qmp/hostname.rs @@ -0,0 +1,9 @@ +use crate::*; + +pub(crate) fn get() -> Result { + let host_name = hostname::get()? + .into_string() + .or_else(|_| err!("Invalid hostname"))?; + + Ok(qapi::GuestHostName { host_name }) +} diff --git a/qga/qmp/mod.rs b/qga/qmp/mod.rs index 38060100af..e855aa4bd7 100644 --- a/qga/qmp/mod.rs +++ b/qga/qmp/mod.rs @@ -34,3 +34,10 @@ macro_rules! qmp { } }}; } + +mod hostname; + +#[no_mangle] +extern "C" fn qmp_guest_get_host_name(errp: *mut *mut sys::Error) -> *mut qapi_sys::GuestHostName { + qmp!(hostname::get(), errp) +} diff --git a/tests/test-qga.c b/tests/test-qga.c index c1b173b3cb..6190e93e0e 100644 --- a/tests/test-qga.c +++ b/tests/test-qga.c @@ -863,6 +863,7 @@ static void test_qga_guest_exec_invalid(gconstpointer fix) static void test_qga_guest_get_host_name(gconstpointer fix) { +#ifdef CONFIG_WITH_RUST const TestFixture *fixture = fix; QDict *ret, *val; @@ -874,6 +875,7 @@ static void test_qga_guest_get_host_name(gconstpointer fix) g_assert(qdict_haskey(val, "host-name")); qobject_unref(ret); +#endif } static void test_qga_guest_get_timezone(gconstpointer fix) diff --git a/util/oslib-posix.c b/util/oslib-posix.c index f15234b5c0..1722c269b8 100644 --- a/util/oslib-posix.c +++ b/util/oslib-posix.c @@ -804,41 +804,6 @@ void sigaction_invoke(struct sigaction *action, action->sa_sigaction(info->ssi_signo, &si, NULL); } -#ifndef HOST_NAME_MAX -# ifdef _POSIX_HOST_NAME_MAX -# define HOST_NAME_MAX _POSIX_HOST_NAME_MAX -# else -# define HOST_NAME_MAX 255 -# endif -#endif - -char *qemu_get_host_name(Error **errp) -{ - long len = -1; - g_autofree char *hostname = NULL; - -#ifdef _SC_HOST_NAME_MAX - len = sysconf(_SC_HOST_NAME_MAX); -#endif /* _SC_HOST_NAME_MAX */ - - if (len < 0) { - len = HOST_NAME_MAX; - } - - /* Unfortunately, gethostname() below does not guarantee a - * NULL terminated string. Therefore, allocate one byte more - * to be sure. */ - hostname = g_new0(char, len + 1); - - if (gethostname(hostname, len) < 0) { - error_setg_errno(errp, errno, - "cannot get hostname"); - return NULL; - } - - return g_steal_pointer(&hostname); -} - size_t qemu_get_host_physmem(void) { #ifdef _SC_PHYS_PAGES diff --git a/util/oslib-win32.c b/util/oslib-win32.c index 051afb217b..804e303c4f 100644 --- a/util/oslib-win32.c +++ b/util/oslib-win32.c @@ -822,19 +822,6 @@ bool qemu_write_pidfile(const char *filename, Error **errp) return true; } -char *qemu_get_host_name(Error **errp) -{ - wchar_t tmp[MAX_COMPUTERNAME_LENGTH + 1]; - DWORD size = G_N_ELEMENTS(tmp); - - if (GetComputerNameW(tmp, &size) == 0) { - error_setg_win32(errp, GetLastError(), "failed close handle"); - return NULL; - } - - return g_utf16_to_utf8(tmp, size, NULL, NULL, NULL); -} - size_t qemu_get_host_physmem(void) { MEMORYSTATUSEX statex; From patchwork Sun Oct 11 20:35:11 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 303138 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.5 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1B0C1C433DF for ; Sun, 11 Oct 2020 20:47:23 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 802AF20674 for ; Sun, 11 Oct 2020 20:47:22 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="O5vB2qgo" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 802AF20674 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:54738 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kRiFV-0007E5-Hw for qemu-devel@archiver.kernel.org; Sun, 11 Oct 2020 16:47:21 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:57866) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kRi67-0002TA-9S for qemu-devel@nongnu.org; Sun, 11 Oct 2020 16:37:39 -0400 Received: from us-smtp-delivery-124.mimecast.com ([63.128.21.124]:36044) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1kRi64-0005b7-W3 for qemu-devel@nongnu.org; Sun, 11 Oct 2020 16:37:38 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1602448656; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=tBSHczW2Lzk3cLtx36KBC74qLkYR3CoBuZtx44+ZG+w=; b=O5vB2qgoN/MEZLtnbrHFo0OT0/Qt/bwJ2JEtyy2Zuav4/kudXfs5kZWzAGGZfiHcE05NIR 08QianhJD3s7Qd12MopFyNswhiqsGDdhBLErTm+/nnHSmXMGVpz1EtReXb9Fkw3GNVTvpf kn54fuLJS6Kyel/0nD+GuUDVXaEYk7c= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-316-gFLx1wC3M2CNkhiBFWngew-1; Sun, 11 Oct 2020 16:37:33 -0400 X-MC-Unique: gFLx1wC3M2CNkhiBFWngew-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id D847A185A0DD for ; Sun, 11 Oct 2020 20:37:32 +0000 (UTC) Received: from localhost (unknown [10.36.110.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id 98FCD100239A; Sun, 11 Oct 2020 20:37:25 +0000 (UTC) From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Subject: [PoCv2 13/15] qga: implement {get,set}-vcpus in Rust Date: Mon, 12 Oct 2020 00:35:11 +0400 Message-Id: <20201011203513.1621355-14-marcandre.lureau@redhat.com> In-Reply-To: <20201011203513.1621355-1-marcandre.lureau@redhat.com> References: <20201011203513.1621355-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=marcandre.lureau@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=63.128.21.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/10/11 16:23:51 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -10 X-Spam_score: -1.1 X-Spam_bar: - X-Spam_report: (-1.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, PDS_OTHER_BAD_TLD=1.999, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=-1, RCVD_IN_MSPIKE_WL=-0.01, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: pbonzini@redhat.com, berrange@redhat.com, armbru@redhat.com, stefanha@redhat.com, =?utf-8?q?Marc-Andr=C3=A9_Lureau?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Marc-André Lureau This is a rewrite of the C version (using the nix & winapi crates). The main difference is that Rust doesn't let you mix const/mut logic, the way transfer_vcpu in C does. The Rust version does introduce some duplication, but is also more strict and can prevent mistakes. Signed-off-by: Marc-André Lureau --- qga/Cargo.toml | 6 ++ qga/commands-posix.c | 159 ------------------------------------------ qga/commands-win32.c | 76 -------------------- qga/commands.c | 14 ++++ qga/qmp/mod.rs | 18 +++++ qga/qmp/vcpus.rs | 161 +++++++++++++++++++++++++++++++++++++++++++ tests/test-qga.c | 2 + 7 files changed, 201 insertions(+), 235 deletions(-) create mode 100644 qga/qmp/vcpus.rs diff --git a/qga/Cargo.toml b/qga/Cargo.toml index 63a419255d..bb86fc543d 100644 --- a/qga/Cargo.toml +++ b/qga/Cargo.toml @@ -9,6 +9,12 @@ common = { path = "../rust/common" } libc = "^0.2.76" hostname = "^0.3.1" +[target."cfg(unix)".dependencies] +nix = "^0.18.0" + +[target."cfg(windows)".dependencies] +winapi = { version = "^0.3.9", features = ["sysinfoapi", "winnt"] } + [lib] path = "lib.rs" crate-type = ["staticlib"] diff --git a/qga/commands-posix.c b/qga/commands-posix.c index 3bffee99d4..2c2c97fbca 100644 --- a/qga/commands-posix.c +++ b/qga/commands-posix.c @@ -2092,165 +2092,6 @@ error: return NULL; } -#define SYSCONF_EXACT(name, errp) sysconf_exact((name), #name, (errp)) - -static long sysconf_exact(int name, const char *name_str, Error **errp) -{ - long ret; - - errno = 0; - ret = sysconf(name); - if (ret == -1) { - if (errno == 0) { - error_setg(errp, "sysconf(%s): value indefinite", name_str); - } else { - error_setg_errno(errp, errno, "sysconf(%s)", name_str); - } - } - return ret; -} - -/* Transfer online/offline status between @vcpu and the guest system. - * - * On input either @errp or *@errp must be NULL. - * - * In system-to-@vcpu direction, the following @vcpu fields are accessed: - * - R: vcpu->logical_id - * - W: vcpu->online - * - W: vcpu->can_offline - * - * In @vcpu-to-system direction, the following @vcpu fields are accessed: - * - R: vcpu->logical_id - * - R: vcpu->online - * - * Written members remain unmodified on error. - */ -static void transfer_vcpu(GuestLogicalProcessor *vcpu, bool sys2vcpu, - char *dirpath, Error **errp) -{ - int fd; - int res; - int dirfd; - static const char fn[] = "online"; - - dirfd = open(dirpath, O_RDONLY | O_DIRECTORY); - if (dirfd == -1) { - error_setg_errno(errp, errno, "open(\"%s\")", dirpath); - return; - } - - fd = openat(dirfd, fn, sys2vcpu ? O_RDONLY : O_RDWR); - if (fd == -1) { - if (errno != ENOENT) { - error_setg_errno(errp, errno, "open(\"%s/%s\")", dirpath, fn); - } else if (sys2vcpu) { - vcpu->online = true; - vcpu->can_offline = false; - } else if (!vcpu->online) { - error_setg(errp, "logical processor #%" PRId64 " can't be " - "offlined", vcpu->logical_id); - } /* otherwise pretend successful re-onlining */ - } else { - unsigned char status; - - res = pread(fd, &status, 1, 0); - if (res == -1) { - error_setg_errno(errp, errno, "pread(\"%s/%s\")", dirpath, fn); - } else if (res == 0) { - error_setg(errp, "pread(\"%s/%s\"): unexpected EOF", dirpath, - fn); - } else if (sys2vcpu) { - vcpu->online = (status != '0'); - vcpu->can_offline = true; - } else if (vcpu->online != (status != '0')) { - status = '0' + vcpu->online; - if (pwrite(fd, &status, 1, 0) == -1) { - error_setg_errno(errp, errno, "pwrite(\"%s/%s\")", dirpath, - fn); - } - } /* otherwise pretend successful re-(on|off)-lining */ - - res = close(fd); - g_assert(res == 0); - } - - res = close(dirfd); - g_assert(res == 0); -} - -GuestLogicalProcessorList *qmp_guest_get_vcpus(Error **errp) -{ - int64_t current; - GuestLogicalProcessorList *head, **link; - long sc_max; - Error *local_err = NULL; - - current = 0; - head = NULL; - link = &head; - sc_max = SYSCONF_EXACT(_SC_NPROCESSORS_CONF, &local_err); - - while (local_err == NULL && current < sc_max) { - GuestLogicalProcessor *vcpu; - GuestLogicalProcessorList *entry; - int64_t id = current++; - char *path = g_strdup_printf("/sys/devices/system/cpu/cpu%" PRId64 "/", - id); - - if (g_file_test(path, G_FILE_TEST_EXISTS)) { - vcpu = g_malloc0(sizeof *vcpu); - vcpu->logical_id = id; - vcpu->has_can_offline = true; /* lolspeak ftw */ - transfer_vcpu(vcpu, true, path, &local_err); - entry = g_malloc0(sizeof *entry); - entry->value = vcpu; - *link = entry; - link = &entry->next; - } - g_free(path); - } - - if (local_err == NULL) { - /* there's no guest with zero VCPUs */ - g_assert(head != NULL); - return head; - } - - qapi_free_GuestLogicalProcessorList(head); - error_propagate(errp, local_err); - return NULL; -} - -int64_t qmp_guest_set_vcpus(GuestLogicalProcessorList *vcpus, Error **errp) -{ - int64_t processed; - Error *local_err = NULL; - - processed = 0; - while (vcpus != NULL) { - char *path = g_strdup_printf("/sys/devices/system/cpu/cpu%" PRId64 "/", - vcpus->value->logical_id); - - transfer_vcpu(vcpus->value, false, path, &local_err); - g_free(path); - if (local_err != NULL) { - break; - } - ++processed; - vcpus = vcpus->next; - } - - if (local_err != NULL) { - if (processed == 0) { - error_propagate(errp, local_err); - } else { - error_free(local_err); - } - } - - return processed; -} - void qmp_guest_set_user_password(const char *username, const char *password, bool crypted, diff --git a/qga/commands-win32.c b/qga/commands-win32.c index 0c3c05484f..1e140b68a6 100644 --- a/qga/commands-win32.c +++ b/qga/commands-win32.c @@ -1740,82 +1740,6 @@ void qmp_guest_set_time(bool has_time, int64_t time_ns, Error **errp) } } -GuestLogicalProcessorList *qmp_guest_get_vcpus(Error **errp) -{ - PSYSTEM_LOGICAL_PROCESSOR_INFORMATION pslpi, ptr; - DWORD length; - GuestLogicalProcessorList *head, **link; - Error *local_err = NULL; - int64_t current; - - ptr = pslpi = NULL; - length = 0; - current = 0; - head = NULL; - link = &head; - - if ((GetLogicalProcessorInformation(pslpi, &length) == FALSE) && - (GetLastError() == ERROR_INSUFFICIENT_BUFFER) && - (length > sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION))) { - ptr = pslpi = g_malloc0(length); - if (GetLogicalProcessorInformation(pslpi, &length) == FALSE) { - error_setg(&local_err, "Failed to get processor information: %d", - (int)GetLastError()); - } - } else { - error_setg(&local_err, - "Failed to get processor information buffer length: %d", - (int)GetLastError()); - } - - while ((local_err == NULL) && (length > 0)) { - if (pslpi->Relationship == RelationProcessorCore) { - ULONG_PTR cpu_bits = pslpi->ProcessorMask; - - while (cpu_bits > 0) { - if (!!(cpu_bits & 1)) { - GuestLogicalProcessor *vcpu; - GuestLogicalProcessorList *entry; - - vcpu = g_malloc0(sizeof *vcpu); - vcpu->logical_id = current++; - vcpu->online = true; - vcpu->has_can_offline = true; - - entry = g_malloc0(sizeof *entry); - entry->value = vcpu; - - *link = entry; - link = &entry->next; - } - cpu_bits >>= 1; - } - } - length -= sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION); - pslpi++; /* next entry */ - } - - g_free(ptr); - - if (local_err == NULL) { - if (head != NULL) { - return head; - } - /* there's no guest with zero VCPUs */ - error_setg(&local_err, "Guest reported zero VCPUs"); - } - - qapi_free_GuestLogicalProcessorList(head); - error_propagate(errp, local_err); - return NULL; -} - -int64_t qmp_guest_set_vcpus(GuestLogicalProcessorList *vcpus, Error **errp) -{ - error_setg(errp, QERR_UNSUPPORTED); - return -1; -} - static gchar * get_net_error_message(gint error) { diff --git a/qga/commands.c b/qga/commands.c index 15478a16e7..a5f8e32ece 100644 --- a/qga/commands.c +++ b/qga/commands.c @@ -577,3 +577,17 @@ GuestFileRead *qmp_guest_file_read(int64_t handle, bool has_count, return read_data; } + +#ifndef CONFIG_WITH_RUST +GuestLogicalProcessorList *qmp_guest_get_vcpus(Error **errp) +{ + error_setg(errp, QERR_UNSUPPORTED); + return NULL; +} + +int64_t qmp_guest_set_vcpus(GuestLogicalProcessorList *vcpus, Error **errp) +{ + error_setg(errp, QERR_UNSUPPORTED); + return 0; +} +#endif diff --git a/qga/qmp/mod.rs b/qga/qmp/mod.rs index e855aa4bd7..7c4d30c7de 100644 --- a/qga/qmp/mod.rs +++ b/qga/qmp/mod.rs @@ -41,3 +41,21 @@ mod hostname; extern "C" fn qmp_guest_get_host_name(errp: *mut *mut sys::Error) -> *mut qapi_sys::GuestHostName { qmp!(hostname::get(), errp) } + +mod vcpus; + +#[no_mangle] +extern "C" fn qmp_guest_get_vcpus( + errp: *mut *mut sys::Error, +) -> *mut qapi_sys::GuestLogicalProcessorList { + qmp!(vcpus::get(), errp) +} + +#[no_mangle] +extern "C" fn qmp_guest_set_vcpus( + vcpus: *const qapi_sys::GuestLogicalProcessorList, + errp: *mut *mut sys::Error, +) -> libc::c_longlong { + let vcpus = unsafe { from_qemu_none(qapi::NewPtr(vcpus)) }; + qmp!(vcpus::set(vcpus), errp, -1) +} diff --git a/qga/qmp/vcpus.rs b/qga/qmp/vcpus.rs new file mode 100644 index 0000000000..f86838355e --- /dev/null +++ b/qga/qmp/vcpus.rs @@ -0,0 +1,161 @@ +#[cfg(unix)] +use std::fs::OpenOptions; +#[cfg(unix)] +use std::io::ErrorKind; +#[cfg(unix)] +use std::os::unix::fs::FileExt; + +#[cfg(windows)] +use winapi::um::{sysinfoapi, winnt}; + +use crate::*; + +#[cfg(target_os = "linux")] +fn get_sysfs_cpu_path(id: i64) -> String { + format!("/sys/devices/system/cpu/cpu{}", id) +} + +#[cfg(target_os = "linux")] +fn set_vcpu(vcpu: &qapi::GuestLogicalProcessor) -> Result<()> { + let path = get_sysfs_cpu_path(vcpu.logical_id); + std::fs::metadata(&path)?; + + let path = format!("{}/online", path); + match OpenOptions::new().read(true).write(true).open(&path) { + Ok(file) => { + let mut buf = [0u8; 1]; + file.read_exact_at(&mut buf, 0)?; + let online = buf[0] != 0; + if vcpu.online != online { + buf[0] = if vcpu.online { b'1' } else { b'0' }; + file.write_all_at(&buf, 0)?; + } + } + Err(e) => { + if e.kind() != ErrorKind::NotFound { + return Err(e.into()); + } else if !vcpu.online { + return err!(format!( + "logical processor #{} can't be offlined", + vcpu.logical_id + )); + } + } + } + + Ok(()) +} + +#[cfg(not(target_os = "linux"))] +fn set_vcpu(_vcpu: &qapi::GuestLogicalProcessor) -> Result<()> { + err!("unimplemented") +} + +pub(crate) fn set(vcpus: Vec) -> Result { + let mut processed = 0; + + for vcpu in &vcpus { + if let Err(e) = set_vcpu(vcpu) { + if processed != 0 { + break; + } + return Err(e); + } + + processed += 1; + } + + Ok(processed) +} + +#[cfg(target_os = "linux")] +pub(crate) fn get() -> Result> { + use nix::unistd::sysconf; + + let mut vcpus = vec![]; + let nproc_conf = match sysconf(unsafe { std::mem::transmute(libc::_SC_NPROCESSORS_CONF) })? { + Some(nproc) => nproc, + None => { + return err!("Indefinite number of processors."); + } + }; + + for logical_id in 0..nproc_conf { + let path = get_sysfs_cpu_path(logical_id); + if std::fs::metadata(&path).is_err() { + continue; + } + + let path = format!("{}/online", path); + let (online, can_offline) = match OpenOptions::new().read(true).open(&path) { + Ok(file) => { + let mut buf = [0u8; 1]; + file.read_exact_at(&mut buf, 0)?; + (buf[0] != 0, Some(true)) + } + Err(e) => { + if e.kind() != ErrorKind::NotFound { + return Err(e.into()); + } + (true, Some(false)) + } + }; + + vcpus.push(qapi::GuestLogicalProcessor { + logical_id, + online, + can_offline, + }); + } + + Ok(vcpus) +} + +#[cfg(target_os = "windows")] +fn get_logical_processor_info() -> Result> { + unsafe { + let mut needed_size = 0; + sysinfoapi::GetLogicalProcessorInformation(std::ptr::null_mut(), &mut needed_size); + let struct_size = std::mem::size_of::() as u32; + if needed_size == 0 || needed_size < struct_size || needed_size % struct_size != 0 { + return err!("Failed to get processor information"); + } + + let nstruct = needed_size / struct_size; + let mut buf = Vec::with_capacity(nstruct as usize); + let result = sysinfoapi::GetLogicalProcessorInformation(buf.as_mut_ptr(), &mut needed_size); + if result == 0 { + return err!("Failed to get processor information"); + } + + let nstruct = needed_size / struct_size; + buf.set_len(nstruct as usize); + Ok(buf) + } +} + +#[cfg(target_os = "windows")] +pub(crate) fn get() -> Result> { + let mut vcpus = vec![]; + + get_logical_processor_info()?.iter().map(|info| { + for _ in 0..info.ProcessorMask.count_ones() { + vcpus.push(qapi::GuestLogicalProcessor { + logical_id: vcpus.len() as i64, + online: true, + can_offline: Some(false), + }); + } + }); + + if vcpus.is_empty() { + return err!("Guest reported zero VCPUs"); + } + + Ok(vcpus) +} + +#[cfg(not(any(target_os = "linux", target_os = "windows")))] +pub(crate) fn get() -> Result> { + err!("unimplemented") +} diff --git a/tests/test-qga.c b/tests/test-qga.c index 6190e93e0e..ff1807531c 100644 --- a/tests/test-qga.c +++ b/tests/test-qga.c @@ -307,6 +307,7 @@ static void test_qga_info(gconstpointer fix) static void test_qga_get_vcpus(gconstpointer fix) { +#ifdef CONFIG_WITH_RUST const TestFixture *fixture = fix; QDict *ret; QList *list; @@ -323,6 +324,7 @@ static void test_qga_get_vcpus(gconstpointer fix) g_assert(qdict_haskey(qobject_to(QDict, entry->value), "logical-id")); qobject_unref(ret); +#endif } static void test_qga_get_fsinfo(gconstpointer fix) From patchwork Sun Oct 11 20:35:12 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 303141 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4543AC433E7 for ; Sun, 11 Oct 2020 20:40:43 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id C97A8207FB for ; Sun, 11 Oct 2020 20:40:42 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="K9taYZpN" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org C97A8207FB Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:38114 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kRi93-00086v-Rp for qemu-devel@archiver.kernel.org; Sun, 11 Oct 2020 16:40:41 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:57886) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kRi6F-0002ng-Mq for qemu-devel@nongnu.org; Sun, 11 Oct 2020 16:37:47 -0400 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:53464) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1kRi6E-0005bl-0M for qemu-devel@nongnu.org; Sun, 11 Oct 2020 16:37:47 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1602448665; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=TeY7imNTlzyA8qZI2q/5+3WkBmAybf/f5KVeNklE1XM=; b=K9taYZpN5y0CX72mik41Q/SgZQEaMKNQoliwxln6q07EncVg5Ro1vxpVKJzq32WVQ7P2nT YSSbRnMj4Emr5J0QhyoB6U3y28ZdL/1KgRTxTQyoEDwp3qg5GnN7+nIXFIOI2aeL63DmQ3 7dvoE1A88W2rlgly4CgV79CozI93vXU= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-197-ew21iFf0NUmw6x9cUr-yAw-1; Sun, 11 Oct 2020 16:37:43 -0400 X-MC-Unique: ew21iFf0NUmw6x9cUr-yAw-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id ABC31185A0C0 for ; Sun, 11 Oct 2020 20:37:42 +0000 (UTC) Received: from localhost (unknown [10.36.110.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id 718F26EF66; Sun, 11 Oct 2020 20:37:36 +0000 (UTC) From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Subject: [PoCv2 14/15] travis: add Rust Date: Mon, 12 Oct 2020 00:35:12 +0400 Message-Id: <20201011203513.1621355-15-marcandre.lureau@redhat.com> In-Reply-To: <20201011203513.1621355-1-marcandre.lureau@redhat.com> References: <20201011203513.1621355-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=marcandre.lureau@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=216.205.24.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/10/11 16:35:36 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=-0.01, RCVD_IN_MSPIKE_WL=-0.01, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: pbonzini@redhat.com, berrange@redhat.com, armbru@redhat.com, stefanha@redhat.com, =?utf-8?q?Marc-Andr=C3=A9_Lureau?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Marc-André Lureau Signed-off-by: Marc-André Lureau --- .travis.yml | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 1054ec5d29..b2835316bc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,6 +23,8 @@ addons: apt: packages: # Build dependencies + - cargo + - rustc - libaio-dev - libattr1-dev - libbrlapi-dev @@ -71,7 +73,7 @@ env: global: - SRC_DIR=".." - BUILD_DIR="build" - - BASE_CONFIG="--disable-docs --disable-tools" + - BASE_CONFIG="--disable-docs --disable-tools --with-rust" - TEST_BUILD_CMD="" - TEST_CMD="make check V=1" # This is broadly a list of "mainline" softmmu targets which have support across the major distros @@ -258,6 +260,8 @@ jobs: # Extra toolchains - gcc-9 - g++-9 + - cargo + - rustc # Build dependencies - libaio-dev - libattr1-dev @@ -325,6 +329,8 @@ jobs: dist: focal addons: apt_packages: + - cargo + - rustc - libaio-dev - libattr1-dev - libbrlapi-dev @@ -358,6 +364,8 @@ jobs: dist: focal addons: apt_packages: + - cargo + - rustc - libaio-dev - libattr1-dev - libbrlapi-dev @@ -390,6 +398,8 @@ jobs: dist: bionic addons: apt_packages: + - cargo + - rustc - libaio-dev - libattr1-dev - libbrlapi-dev @@ -432,6 +442,8 @@ jobs: dist: bionic addons: apt_packages: + - cargo + - rustc - libaio-dev - libattr1-dev - libcap-ng-dev @@ -461,6 +473,8 @@ jobs: dist: bionic addons: apt_packages: + - cargo + - rustc - libgcrypt20-dev - libgnutls28-dev env: @@ -472,6 +486,8 @@ jobs: compiler: clang addons: apt_packages: + - cargo + - rustc - libaio-dev - libattr1-dev - libbrlapi-dev From patchwork Sun Oct 11 20:35:13 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 271541 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-14.5 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, MENTIONS_GIT_HOSTING, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 00DC0C433E7 for ; Sun, 11 Oct 2020 20:50:29 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 7B9D920674 for ; Sun, 11 Oct 2020 20:50:28 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="Z/YE4wHp" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 7B9D920674 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:33580 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kRiIV-0001oE-KG for qemu-devel@archiver.kernel.org; Sun, 11 Oct 2020 16:50:27 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:57930) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kRi6R-0003FR-DE for qemu-devel@nongnu.org; Sun, 11 Oct 2020 16:37:59 -0400 Received: from us-smtp-delivery-124.mimecast.com ([63.128.21.124]:50287) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1kRi6P-0005cM-Eq for qemu-devel@nongnu.org; Sun, 11 Oct 2020 16:37:59 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1602448676; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=voPjCiZWVDBPQH65LrK+W3HZpGd+P96aarosFlVdCOo=; b=Z/YE4wHpkKlOUSG/gQ6vh+wYVjkNUd3f+PyFAJlsq6Kte4RePRV7iG3paMn+v/wtRsHRmP 43OecmKWaPFluMHlghgfYYjVIB6L+UBmCaENRsQxg98wjcDq+tXmIycbLuP1nWU2cMDf6T gTIwJeuxvvwoZcQ3wA0zpWFGXwUQB1g= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-534-ho2pcMK4P1-31mvpUrfFaA-1; Sun, 11 Oct 2020 16:37:53 -0400 X-MC-Unique: ho2pcMK4P1-31mvpUrfFaA-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id C1EBE185A0C0 for ; Sun, 11 Oct 2020 20:37:52 +0000 (UTC) Received: from localhost (unknown [10.36.110.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id 8733660C05; Sun, 11 Oct 2020 20:37:46 +0000 (UTC) From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Subject: [PoCv2 15/15] rust: use vendored-sources Date: Mon, 12 Oct 2020 00:35:13 +0400 Message-Id: <20201011203513.1621355-16-marcandre.lureau@redhat.com> In-Reply-To: <20201011203513.1621355-1-marcandre.lureau@redhat.com> References: <20201011203513.1621355-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=marcandre.lureau@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=63.128.21.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/10/11 16:23:51 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -30 X-Spam_score: -3.1 X-Spam_bar: --- X-Spam_report: (-3.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=-1, RCVD_IN_MSPIKE_WL=-0.01, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: pbonzini@redhat.com, berrange@redhat.com, armbru@redhat.com, stefanha@redhat.com, =?utf-8?q?Marc-Andr=C3=A9_Lureau?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Marc-André Lureau Most likely, QEMU will want tighter control over the sources, rather than relying on crates.io downloading, use a git submodule with all the dependencies. "cargo vendor" makes that simple. Signed-off-by: Marc-André Lureau --- .cargo/config | 5 +++++ .gitmodules | 3 +++ configure | 8 ++++++++ rust/vendored | 1 + scripts/cargo_wrapper.py | 1 + 5 files changed, 18 insertions(+) create mode 100644 .cargo/config create mode 160000 rust/vendored diff --git a/.cargo/config b/.cargo/config new file mode 100644 index 0000000000..a8c55940d5 --- /dev/null +++ b/.cargo/config @@ -0,0 +1,5 @@ +[source.crates-io] +replace-with = "vendored-sources" + +[source.vendored-sources] +directory = "rust/vendored" diff --git a/.gitmodules b/.gitmodules index 2bdeeacef8..62a2be12b9 100644 --- a/.gitmodules +++ b/.gitmodules @@ -64,3 +64,6 @@ [submodule "roms/vbootrom"] path = roms/vbootrom url = https://git.qemu.org/git/vbootrom.git +[submodule "rust/vendored"] + path = rust/vendored + url = https://github.com/elmarco/qemu-rust-vendored.git diff --git a/configure b/configure index 7945ceac63..702546d87f 100755 --- a/configure +++ b/configure @@ -1932,6 +1932,14 @@ if test "$with_rust" = auto && has cargo; then with_rust=yes fi +case "$with_rust" in + yes) + if test -e "${source_path}/.git" && test $git_update = 'yes' ; then + git_submodules="${git_submodules} rust/vendored" + fi + ;; +esac + # Check that the C compiler works. Doing this here before testing # the host CPU ensures that we had a valid CC to autodetect the # $cpu var (and we should bail right here if that's not the case). diff --git a/rust/vendored b/rust/vendored new file mode 160000 index 0000000000..71ee65d042 --- /dev/null +++ b/rust/vendored @@ -0,0 +1 @@ +Subproject commit 71ee65d042606d18de3175d67f9e4e4b78a1f865 diff --git a/scripts/cargo_wrapper.py b/scripts/cargo_wrapper.py index 164fad5123..4a0673407b 100644 --- a/scripts/cargo_wrapper.py +++ b/scripts/cargo_wrapper.py @@ -51,6 +51,7 @@ def build_lib(args: argparse.Namespace) -> None: target_dir, "--manifest-path", manifest_path, + "--offline", ] if args.target_triple: cargo_cmd += ["--target", args.target_triple]