qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Eric Blake <eblake@redhat.com>
To: "Markus Armbruster" <armbru@redhat.com>,
	"Marc-André Lureau" <marcandre.lureau@gmail.com>
Cc: qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH v5 02/20] qapi.py: add a simple #ifdef conditional
Date: Wed, 7 Sep 2016 13:49:15 -0500	[thread overview]
Message-ID: <e2a8f720-fc40-f7cf-f3da-e37aa09db851@redhat.com> (raw)
In-Reply-To: <87zinjde01.fsf@dusky.pond.sub.org>

[-- Attachment #1: Type: text/plain, Size: 5964 bytes --]

On 09/07/2016 08:40 AM, Markus Armbruster wrote:
>>>>>> Yet another option is to add 'ifdef' keys to the definitions
>>>>>> themselves, i.e.
>>>>>>
>>>>>>     { 'command': 'query-gic-capabilities', 'returns': ['GICCapability'],
>>>>>>       'ifdef': 'TARGET_ARM' }

Seems like it might be useful; could even be expanded to:

{ 'command': 'query-arm-x86', 'returns': ['Foo'],
  'ifdef': [ 'TARGET_ARM', 'TARGET_X86' ] }

unless you are okay with it instead being:

{ 'command': 'query-arm-x86', 'returns': ['Foo'],
  'ifdef': 'TARGET_ARM || TARGET_X86' }

Either way, we need to make sure that whatever we put here is easy to
translate into the appropriate generated code; and keeping in mind that
while '#if A || B' makes sense to the preprocessor, '#ifdef A || B' does
not.

>>>> Fixable the same way as always when a definition needs to grow
>>>> additional properties, but the syntax only provides a single value: make
>>>> that single value an object, and the old non-object value syntactic
>>>> sugar for the equivalent object value.  We've previously discussed this
>>>> technique in the context of giving command arguments default values.
>>>> I'm not saying this is what we should do here, only pointing out it's
>>>> possible.
>>>>
>>>
>>> Ok, but let's find something, if possible simple and convenient, no?
>>
>> I agree it needs to be simple, both the interface (QAPI language) and
>> the implementation.  However, I don't like "first past the post".  I
>> prefer to explore the design space a bit.

Another nice thing about expanding it by changing 'name':'typestr' to be
sugar for 'name':{'type':'typestr'} is that QMP introspection is already
prepared to expose a dictionary of attributes (type being one, and
ifdef'ness being another) per member, so we already would have a nice
mapping between qapi JSON files (a member name tied to a dictionary) and
the generated output.

>>
>> So let me explore the "add 'ifdef' keys to definitions" corner of the
>> QAPI language design space.
>>
>> Easily done for top-level definitions, because they're all JSON objects.
>> Could even add it to the include directive if we wanted to.
>>
>> Less easily done for enumeration, struct, union and alternate members.
>> Note that command and event arguments specified inline are a special
>> case of struct members.
>>

and ideally, whatever we can do for a named struct, we can also do for
an anonymous inlined struct for the command and event arguments.

> 
> I ported qmp-commands.hx's #if to qapi-schema.json.  The TARGET_FOO are
> poisoned, so I commented them out.  There's a CONFIG_SPICE left, which
> will do for testing.

Obviously, we'd have to find a way to work around the poisoned ifdef
names, but the idea makes some sense to me.

> 
> I also turned key 'gen': false into 'if': false.  Possibly a bad idea.

Maybe, maybe not. We have so few that it's easy to convert them all in
one go, at which point you are just giving directives to the code
generator: if the 'if' key is present, it controls what gets omitted
(either the omitted code is gated by #if (or #ifdef) of the gate string,
or 'if':false means the generator omits the code altogether).

> @@ -475,16 +475,18 @@ arguments for the user's function out of an input QDict, calls the
>  user's function, and if it succeeded, builds an output QObject from
>  its return value.
>  
> +FIXME document 'if'
> +

And in particular, what the string must look like (will it be fed to
generated #if or to generated #ifdef?  What if you have more than one
conditional?)

> +++ b/qapi-schema.json
> @@ -1269,7 +1269,9 @@
>  #
>  # Since: 0.14.0
>  ##
> -{ 'command': 'query-spice', 'returns': 'SpiceInfo' }
> +{ 'command': 'query-spice',
> +  'if': 'defined(CONFIG_SPICE)',
> +  'returns': 'SpiceInfo' }

So the idea here is that qemu built without SPICE support would
completely lack the query-spice command.  This is currently detectable
during 'query-commands' but NOT detectable during 'query-qmp-schema';
but after the patch, we could begin to make the introspection likewise
hide the unused command.  Sounds useful.

>  
>  ##
>  # @BalloonInfo:
> @@ -2355,6 +2357,7 @@
>  # Since: 2.5
>  ##
>  { 'command': 'dump-skeys',
> +#  'if': 'defined(TARGET_S390X)',
>    'data': { 'filename': 'str' } }

And here you ran into the poisoned variable problem.  Obviously
something to be solved if we like the overall idea.

> +++ b/scripts/qapi-introspect.py
> @@ -30,8 +30,6 @@ def to_json(obj, level=0):
>          ret = '{' + ', '.join(elts) + '}'
>      else:
>          assert False                # not implemented
> -    if level == 1:
> -        ret = '\n' + ret
>      return ret
>  
>  
> @@ -69,8 +67,15 @@ class QAPISchemaGenIntrospectVisitor(QAPISchemaVisitor):
>  extern const char %(c_name)s[];
>  ''',
>                            c_name=c_name(name))
> -        lines = to_json(jsons).split('\n')
> -        c_string = '\n    '.join([to_c_string(line) for line in lines])
> +        c_string = '"["'
> +        for i in jsons:
> +            js, genif = i
> +            # FIXME blank lines are off
> +            c_string += gen_pp_if(genif or True)
> +            c_string += '\n    ' + to_c_string(to_json(js) + ', ')
> +            c_string += gen_pp_endif(genif or True)

And this change to introspection output shows the true power - by having
the conditional expression be part of the .json QAPI file, we can now
reflect the conditions through ALL parts of the generated code, instead
of having discrepancies between query-commands vs. query-qmp-schema.

At any rate, for a quick day's hack, I like this approach for feeling
like it fits in with the QAPI language, rather than being bolted on as
additional non-JSON syntax.

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

  parent reply	other threads:[~2016-09-07 18:49 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-08-17 16:57 [Qemu-devel] [PATCH v5 00/20] qapi: remove the 'middle' mode Marc-André Lureau
2016-08-17 16:57 ` [Qemu-devel] [PATCH v5 01/20] tests: do qmp introspect validation per target Marc-André Lureau
2016-08-17 16:57 ` [Qemu-devel] [PATCH v5 02/20] qapi.py: add a simple #ifdef conditional Marc-André Lureau
2016-09-06 12:35   ` Markus Armbruster
2016-09-06 13:17     ` Marc-André Lureau
2016-09-06 15:58       ` Markus Armbruster
2016-09-06 16:44         ` Marc-André Lureau
2016-09-07  8:44           ` Markus Armbruster
2016-09-07 13:40             ` Markus Armbruster
2016-09-07 14:23               ` Marc-André Lureau
2016-09-07 18:49               ` Eric Blake [this message]
2016-08-17 16:57 ` [Qemu-devel] [PATCH v5 03/20] build-sys: make qemu qapi per-target Marc-André Lureau
2016-08-17 16:57 ` [Qemu-devel] [PATCH v5 04/20] build-sys: use config headers to generate qapi Marc-André Lureau
2016-08-17 16:57 ` [Qemu-devel] [PATCH v5 05/20] qapi: configure the schema Marc-André Lureau
2016-08-17 16:57 ` [Qemu-devel] [PATCH v5 06/20] build-sys: define QEMU_VERSION_{MAJOR, MINOR, MICRO} Marc-André Lureau
2016-08-17 16:57 ` [Qemu-devel] [PATCH v5 07/20] qapi-schema: use generated marshaller for 'qmp_capabilities' Marc-André Lureau
2016-08-17 16:57 ` [Qemu-devel] [PATCH v5 08/20] qapi-schema: add 'device_add' Marc-André Lureau
2016-08-17 16:57 ` [Qemu-devel] [PATCH v5 09/20] monitor: simplify invalid_qmp_mode() Marc-André Lureau
2016-08-17 16:57 ` [Qemu-devel] [PATCH v5 10/20] monitor: register gen:false commands manually Marc-André Lureau
2016-08-17 16:57 ` [Qemu-devel] [PATCH v5 11/20] qapi: export the marshallers Marc-André Lureau
2016-08-17 16:57 ` [Qemu-devel] [PATCH v5 12/20] monitor: use qmp_find_command() (using generated qapi code) Marc-André Lureau
2016-08-17 16:57 ` [Qemu-devel] [PATCH v5 13/20] monitor: implement 'qmp_query_commands' without qmp_cmds Marc-André Lureau
2016-08-17 16:57 ` [Qemu-devel] [PATCH v5 14/20] monitor: remove mhandler.cmd_new Marc-André Lureau
2016-08-17 16:57 ` [Qemu-devel] [PATCH v5 15/20] qapi: remove the "middle" mode Marc-André Lureau
2016-08-17 16:57 ` [Qemu-devel] [PATCH v5 16/20] qapi: check invalid arguments on no-args commands Marc-André Lureau
2016-08-17 16:57 ` [Qemu-devel] [PATCH v5 17/20] monitor: use qmp_dispatch() Marc-André Lureau
2016-08-17 17:04   ` Marc-André Lureau
2016-08-17 16:57 ` [Qemu-devel] [PATCH v5 18/20] build-sys: remove qmp-commands-old.h Marc-André Lureau
2016-08-17 16:57 ` [Qemu-devel] [PATCH v5 19/20] qmp-commands.hx: fix some styling Marc-André Lureau
2016-08-17 16:57 ` [Qemu-devel] [PATCH v5 20/20] Replace qmp-commands.hx by doc/qmp-commands.txt Marc-André Lureau
2016-09-09 12:43   ` Markus Armbruster

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=e2a8f720-fc40-f7cf-f3da-e37aa09db851@redhat.com \
    --to=eblake@redhat.com \
    --cc=armbru@redhat.com \
    --cc=marcandre.lureau@gmail.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).