Paolo Bonzini <pbonz...@redhat.com> writes: > On 21/01/20 06:49, Markus Armbruster wrote: >> Paolo Bonzini <pbonz...@redhat.com> writes: >> >>> On 13/01/20 15:01, Markus Armbruster wrote: >>>> Philippe Mathieu-Daudé <phi...@redhat.com> writes: >>>> >>>>> When configured with --without-default-devices and setting >>>>> MC146818RTC=n, the build fails: >>>>> >>>>> LINK x86_64-softmmu/qemu-system-x86_64 >>>>> /usr/bin/ld: qapi/qapi-commands-misc-target.o: in function >>>>> `qmp_marshal_rtc_reset_reinjection': >>>>> qapi/qapi-commands-misc-target.c:46: undefined reference to >>>>> `qmp_rtc_reset_reinjection' >>>>> /usr/bin/ld: qapi/qapi-commands-misc-target.c:46: undefined reference >>>>> to `qmp_rtc_reset_reinjection' >>>>> collect2: error: ld returned 1 exit status >>>>> make[1]: *** [Makefile:206: qemu-system-x86_64] Error 1 >>>>> make: *** [Makefile:483: x86_64-softmmu/all] Error 2 >>>>> >>>>> This patch tries to fix this, but this is incorrect because QAPI >>>>> scripts only provide TARGET definitions, so with MC146818RTC=y we >>>>> get: >>>>> >>>>> hw/rtc/mc146818rtc.c:113:6: error: no previous prototype for >>>>> ‘qmp_rtc_reset_reinjection’ [-Werror=missing-prototypes] >>>>> 113 | void qmp_rtc_reset_reinjection(Error **errp) >>>>> | ^~~~~~~~~~~~~~~~~~~~~~~~~ >>>>> cc1: all warnings being treated as errors >>>>> make[1]: *** [rules.mak:69: hw/rtc/mc146818rtc.o] Error 1 >>>>> >>>>> Any idea? :) >>>>> >>>>> Signed-off-by: Philippe Mathieu-Daudé <phi...@redhat.com> >>>>> --- >>>>> qapi/misc-target.json | 2 +- >>>>> 1 file changed, 1 insertion(+), 1 deletion(-) >>>>> >>>>> diff --git a/qapi/misc-target.json b/qapi/misc-target.json >>>>> index a00fd821eb..8e49c113d1 100644 >>>>> --- a/qapi/misc-target.json >>>>> +++ b/qapi/misc-target.json >>>>> @@ -41,7 +41,7 @@ >>>>> # >>>>> ## >>>>> { 'command': 'rtc-reset-reinjection', >>>>> - 'if': 'defined(TARGET_I386)' } >>>>> + 'if': 'defined(TARGET_I386) && defined(CONFIG_MC146818RTC)' } >>>>> >>>>> >>>>> ## >>>> >>>> The generated qapi-commands-misc-target.h duly has >>>> >>>> #if defined(TARGET_I386) && defined(CONFIG_MC146818RTC) >>>> void qmp_rtc_reset_reinjection(Error **errp); >>>> void qmp_marshal_rtc_reset_reinjection(QDict *args, QObject **ret, >>>> Error **errp); >>>> #endif /* defined(TARGET_I386) && defined(CONFIG_MC146818RTC) */ >>>> >>>> mc146818rtc.c includes it. But since it doesn't include >>>> config-devices.h, CONFIG_MC146818RTC remains undefined, and the >>>> prototype gets suppressed. >>>> >>>> Crude fix: make mc146818rtc.c #include "config-devices.h". >>> >>> Can we modify the code generator to leave out the #if from the header, >>> and only include it in the .c file? An extra prototype is harmless. >> >> Is *everything* we generate into headers just as harmless? > > It should be, since it's just the C version of some JSON. The only > problematic thing could be different definitions of the same command for > multiple targets, and I think we want to avoid that anyway. > > To see it a different way, these are the "C bindings" to QMP, just that > the implementation is an in-process call rather than RPC. If the QAPI > code generator was also able to generate Python bindings and the like, > they would have to be the same for all QEMU binaries, wouldn't they?
Ommitting the kind of #if we've been discussing is relatively harmless: #if defined(TARGET_I386) void qmp_rtc_reset_reinjection(Error **errp); void qmp_marshal_rtc_reset_reinjection(QDict *args, QObject **ret, Error **errp); #endif /* defined(TARGET_I386) */ But what about this one, in qapi-types-block-core.h: typedef enum BlockdevDriver { BLOCKDEV_DRIVER_BLKDEBUG, [...] #if defined(CONFIG_REPLICATION) BLOCKDEV_DRIVER_REPLICATION, #endif /* defined(CONFIG_REPLICATION) */ [...] BLOCKDEV_DRIVER__MAX, } BlockdevDriver; If I omit it in the header, I then have to omit it in qapi-types-block-core.c's const QEnumLookup BlockdevDriver_lookup = { .array = (const char *const[]) { [BLOCKDEV_DRIVER_BLKDEBUG] = "blkdebug", [...] #if defined(CONFIG_REPLICATION) [BLOCKDEV_DRIVER_REPLICATION] = "replication", #endif /* defined(CONFIG_REPLICATION) */ [...] }, .size = BLOCKDEV_DRIVER__MAX }; and God knows what else. But I must not omit it in qapi-introspect.c's QLIT_QDICT(((QLitDictEntry[]) { { "meta-type", QLIT_QSTR("enum"), }, { "name", QLIT_QSTR("245"), }, { "values", QLIT_QLIST(((QLitObject[]) { QLIT_QSTR("blkdebug"), [...] #if defined(CONFIG_REPLICATION) QLIT_QSTR("replication"), #endif /* defined(CONFIG_REPLICATION) */ [...] {} })), }, {} })), because that would defeat introspection. I smell a swamp. I'd rather not complicate the generator to support not including a header I feel we *should* include. #ifdef CONFIG_FOO can occur not just in QAPI-generated code, and neglecting to include the relevant header can cause *nasty* problems not just in QAPI-generated code. Like inconsistent struct definitions in separate compilation units. Been there, debugged that, wasn't fun, do not want to go there again.