On Tue, Mar 01, 2016 at 09:26:21AM +1000, Peter Hutterer wrote: > This switches the scanner to generate doxygen-compatible tags for the > generated protocol headers, and hooks up the doxygen build to generate server > and client-side API documentation. That documentation is now in > Client/ and Server/, respectively. > > GENERATE_HTML is on by default and must be disabled for the xml/man targets to > avoid messing up the new documentation. We disable all three three targets in > the doxyfile (xml and man default to NO anyway) to make it obvious that they > need to be set in the per-target instructions. > > Each protocol is a separate doxygen @page, with each interface a @subpage. > Wayland only has one protocol, wayland-protocols will have these nested. > Each protocol page has a list of interfaces and the copyright and description > where available. > All interfaces are grouped by doxygen @defgroup and @ingroups and appear in > "Modules" in the generated output. Each interface subpage has the description > and a link to the actual API doc. > Function, struct and #defines are documented in doxygen style and associated > with the matching interface. > > Note that pages and groups have fixed HTML file names and are directly > linkable/bookmark-able. > > The @mainpage is a separate file that's included at build time. It doesn't > contain much other than links to where the interesting bits are. It's a static > file though that supports markdown, so we can extend it easily in the future. > > For doxygen we need the new options EXTRACT_ALL and OPTIMIZE_OUTPUT_FOR_C so > it scans C code properly. EXTRACT_STATIC is needed since most of the protocol > hooks are static. > > Signed-off-by: Peter Hutterer <[email protected]>
Reviewed-by: Bryce Harrington <[email protected]> > --- > Changes to v3: > - disable GENERATE_HTML/XML/MAN in the doxyfile > > doc/doxygen/Makefile.am | 27 ++++- > doc/doxygen/mainpage.dox | 13 +++ > doc/doxygen/wayland.doxygen.in | 6 ++ > src/scanner.c | 220 > +++++++++++++++++++++++++++-------------- > 4 files changed, 188 insertions(+), 78 deletions(-) > create mode 100644 doc/doxygen/mainpage.dox > > diff --git a/doc/doxygen/Makefile.am b/doc/doxygen/Makefile.am > index a8bb95f..e80c401 100644 > --- a/doc/doxygen/Makefile.am > +++ b/doc/doxygen/Makefile.am > @@ -1,7 +1,11 @@ > > .SUFFIXES = .gv .png .map > > -noinst_DATA = xml/Client/index.xml xml/Server/index.xml > +noinst_DATA = \ > + xml/Client/index.xml \ > + xml/Server/index.xml \ > + html/Client/index.html \ > + html/Server/index.html > dist_noinst_DATA = wayland.doxygen.in > > scanned_src_files_shared = \ > @@ -27,6 +31,17 @@ scanned_src_files_man = > \ > $(top_srcdir)/src/wayland-client.h \ > $(top_srcdir)/src/wayland-client-core.h > > +extra_doxygen = \ > + mainpage.dox > + > +extra_doxygen_Server = \ > + $(top_builddir)/protocol/wayland-server-protocol.h \ > + $(extra_doxygen) > + > +extra_doxygen_Client = \ > + $(top_builddir)/protocol/wayland-client-protocol.h \ > + $(extra_doxygen) > + > diagramsdir := $(srcdir)/dot > diagramssrc := $(wildcard $(diagramsdir)/*.gv) > diagrams := $(patsubst $(diagramsdir)/%,xml/%,$(diagramssrc:.gv=.png)) > @@ -38,7 +53,7 @@ diagram_maps := $(patsubst > $(diagramsdir)/%,xml/%,$(diagramssrc:.gv=.map)) > dist_man3_MANS = $(shell test -d man && find man/man3 -name "wl_*.3" -printf > "man/man3/%P\n") > > # Listing various directories that might need to be created. > -alldirs := xml xml/Client xml/Server man/man3 > +alldirs := xml xml/Client xml/Server man/man3 html/Client html/Server > > $(diagrams): $(diagramssrc) > > @@ -51,6 +66,13 @@ xml/%/index.xml: $(top_srcdir)/src/scanner.c > $(scanned_src_files_%) wayland.doxy > echo "INPUT= $(scanned_src_files_$*)"; \ > ) | $(DOXYGEN) - > > +html/%/index.html: $(scanned_src_files_%) wayland.doxygen $(diagrams) > $(diagram_maps) | html/% > + $(AM_V_GEN)(cat wayland.doxygen; \ > + echo "GENERATE_HTML=YES"; \ > + echo "HTML_OUTPUT=html/$*"; \ > + echo "INPUT= $(scanned_src_files_$*) $(extra_doxygen_$*)"; \ > + ) | $(DOXYGEN) - > + > man/man3/wl_display.3: $(top_srcdir)/src/scanner.c $(scanned_src_files_man) > wayland.doxygen | man/man3 > $(AM_V_GEN)(cat wayland.doxygen; \ > echo "GENERATE_MAN=YES"; \ > @@ -74,6 +96,7 @@ all-local: man/man3/wl_display.3 > > clean-local: > rm -rf xml/ > + rm -rf html/ > rm -rf man/ > > EXTRA_DIST = $(diagramssrc) > diff --git a/doc/doxygen/mainpage.dox b/doc/doxygen/mainpage.dox > new file mode 100644 > index 0000000..8f9bf03 > --- /dev/null > +++ b/doc/doxygen/mainpage.dox > @@ -0,0 +1,13 @@ > +/** > + * @mainpage > + * Wayland protocol API documentation. > + * > + * @section ifaces Interfaces > + * For the list of available interfaces, please see the > + * <a href="modules.html">modules</a> list. > + * > + * @section protocols Protocols > + * For the list of protocols, please see the > + * <a href="pages.html">Related Pages</a>. > + * > + */ > diff --git a/doc/doxygen/wayland.doxygen.in b/doc/doxygen/wayland.doxygen.in > index fb76b12..9d7fa0c 100644 > --- a/doc/doxygen/wayland.doxygen.in > +++ b/doc/doxygen/wayland.doxygen.in > @@ -13,4 +13,10 @@ MACRO_EXPANSION = YES > EXPAND_ONLY_PREDEF = YES > DOT_MULTI_TARGETS = YES > ALIASES += comment{1}="/* \1 *<!-- -->/" > +OPTIMIZE_OUTPUT_FOR_C = YES > +EXTRACT_ALL = YES > +EXTRACT_STATIC = YES > +# These must be set in the Makefile > GENERATE_HTML = NO > +GENERATE_XML = NO > +GENERATE_MAN = NO > diff --git a/src/scanner.c b/src/scanner.c > index d3e2328..5fbc2df 100644 > --- a/src/scanner.c > +++ b/src/scanner.c > @@ -877,6 +877,34 @@ character_data(void *data, const XML_Char *s, int len) > } > > static void > +format_text_to_comment(const char *text, bool standalone_comment) > +{ > + int bol = 1, start = 0, i, length; > + bool comment_started = !standalone_comment; > + > + length = strlen(text); > + for (i = 0; i <= length; i++) { > + if (bol && (text[i] == ' ' || text[i] == '\t')) { > + continue; > + } else if (bol) { > + bol = 0; > + start = i; > + } > + if (text[i] == '\n' || > + (text[i] == '\0' && !(start == i))) { > + printf("%s%s%.*s\n", > + comment_started ? " *" : "/*", > + i > start ? " " : "", > + i - start, text + start); > + bol = 1; > + comment_started = true; > + } > + } > + if (comment_started && standalone_comment) > + printf(" */\n\n"); > +} > + > +static void > emit_opcodes(struct wl_list *message_list, struct interface *interface) > { > struct message *m; > @@ -898,9 +926,11 @@ emit_opcode_versions(struct wl_list *message_list, > struct interface *interface) > { > struct message *m; > > - wl_list_for_each(m, message_list, link) > + wl_list_for_each(m, message_list, link) { > + printf("/**\n * @ingroup iface_%s\n */\n", interface->name); > printf("#define %s_%s_SINCE_VERSION\t%d\n", > interface->uppercase_name, m->uppercase_name, m->since); > + } > > printf("\n"); > } > @@ -940,6 +970,7 @@ emit_stubs(struct wl_list *message_list, struct interface > *interface) > struct arg *a, *ret; > int has_destructor, has_destroy; > > + printf("/** @ingroup iface_%s */\n", interface->name); > printf("static inline void\n" > "%s_set_user_data(struct %s *%s, void *user_data)\n" > "{\n" > @@ -948,6 +979,7 @@ emit_stubs(struct wl_list *message_list, struct interface > *interface) > interface->name, interface->name, interface->name, > interface->name); > > + printf("/** @ingroup iface_%s */\n", interface->name); > printf("static inline void *\n" > "%s_get_user_data(struct %s *%s)\n" > "{\n" > @@ -981,7 +1013,8 @@ emit_stubs(struct wl_list *message_list, struct > interface *interface) > exit(EXIT_FAILURE); > } > > - if (!has_destroy && strcmp(interface->name, "wl_display") != 0) > + if (!has_destroy && strcmp(interface->name, "wl_display") != 0) { > + printf("/** @ingroup iface_%s */\n", interface->name); > printf("static inline void\n" > "%s_destroy(struct %s *%s)\n" > "{\n" > @@ -990,6 +1023,7 @@ emit_stubs(struct wl_list *message_list, struct > interface *interface) > "}\n\n", > interface->name, interface->name, interface->name, > interface->name); > + } > > if (wl_list_empty(message_list)) > return; > @@ -1009,6 +1043,11 @@ emit_stubs(struct wl_list *message_list, struct > interface *interface) > ret = a; > } > > + printf("/**\n" > + " * @ingroup iface_%s\n", interface->name); > + if (m->description && m->description->text) > + format_text_to_comment(m->description->text, false); > + printf(" */\n"); > if (ret && ret->interface_name == NULL) > printf("static inline void *\n"); > else if (ret) > @@ -1104,6 +1143,17 @@ emit_event_wrappers(struct wl_list *message_list, > struct interface *interface) > return; > > wl_list_for_each(m, message_list, link) { > + printf("/**\n" > + " * @ingroup iface_%s\n" > + " * Sends an %s event to the client owning the > resource.\n", > + interface->name, > + m->name); > + printf("* @param resource_ The client's resource\n"); > + wl_list_for_each(a, &m->arg_list, link) { > + if (a->summary) > + printf(" * @param %s %s\n", a->name, > a->summary); > + } > + printf(" */\n"); > printf("static inline void\n" > "%s_send_%s(struct wl_resource *resource_", > interface->name, m->name); > @@ -1150,28 +1200,23 @@ emit_enumerations(struct interface *interface) > > if (desc) { > printf("/**\n"); > - desc_dump(desc->summary, > - " * %s_%s - ", > - interface->name, e->name); > - wl_list_for_each(entry, &e->entry_list, link) { > - desc_dump(entry->summary, > - " * @%s_%s_%s: ", > - interface->uppercase_name, > - e->uppercase_name, > - entry->uppercase_name); > - } > - if (desc->text) { > - printf(" *\n"); > - desc_dump(desc->text, " * "); > - } > + printf(" * @ingroup iface_%s\n", interface->name); > + format_text_to_comment(desc->summary, false); > + if (desc->text) > + format_text_to_comment(desc->text, false); > printf(" */\n"); > } > printf("enum %s_%s {\n", interface->name, e->name); > - wl_list_for_each(entry, &e->entry_list, link) > + wl_list_for_each(entry, &e->entry_list, link) { > + if (entry->summary) > + printf("\t/**\n" > + "\t * %s\n" > + "\t */\n", entry->summary); > printf("\t%s_%s_%s = %s,\n", > interface->uppercase_name, > e->uppercase_name, > entry->uppercase_name, entry->value); > + } > printf("};\n"); > printf("#endif /* %s_%s_ENUM */\n\n", > interface->uppercase_name, e->uppercase_name); > @@ -1188,20 +1233,11 @@ emit_structs(struct wl_list *message_list, struct > interface *interface, enum sid > if (wl_list_empty(message_list)) > return; > > - if (interface->description) { > - struct description *desc = interface->description; > - printf("/**\n"); > - desc_dump(desc->summary, " * %s - ", interface->name); > - wl_list_for_each(m, message_list, link) { > - struct description *mdesc = m->description; > - desc_dump(mdesc ? mdesc->summary : "(none)", > - " * @%s: ", > - m->name); > - } > - printf(" *\n"); > - desc_dump(desc->text, " * "); > - printf(" */\n"); > - } > + printf("/**\n"); > + printf(" * @ingroup iface_%s\n", interface->name); > + printf(" * @struct %s_%s\n", interface->name, > + (side == SERVER) ? "interface" : "listener"); > + printf(" */\n"); > printf("struct %s_%s {\n", interface->name, > (side == SERVER) ? "interface" : "listener"); > > @@ -1209,24 +1245,24 @@ emit_structs(struct wl_list *message_list, struct > interface *interface, enum sid > struct description *mdesc = m->description; > > printf("\t/**\n"); > - desc_dump(mdesc ? mdesc->summary : "(none)", > - "\t * %s - ", m->name); > - wl_list_for_each(a, &m->arg_list, link) { > - if (side == SERVER && a->type == NEW_ID && > - a->interface_name == NULL) > - printf("\t * @interface: name of the objects > interface\n" > - "\t * @version: version of the objects > interface\n"); > - > - > - desc_dump(a->summary ? a->summary : "(none)", > - "\t * @%s: ", a->name); > - } > if (mdesc) { > + if (mdesc->summary) > + printf("\t * %s\n", mdesc->summary); > printf("\t *\n"); > desc_dump(mdesc->text, "\t * "); > } > + wl_list_for_each(a, &m->arg_list, link) { > + if (side == SERVER && a->type == NEW_ID && > + a->interface_name == NULL) > + printf("\t * @param interface name of the > objects interface\n" > + "\t * @param version version of the > objects interface\n"); > + > + if (a->summary) > + printf("\t * @param %s %s\n", a->name, > + a->summary); > + } > if (m->since > 1) { > - printf("\t * @since: %d\n", m->since); > + printf("\t * @since %d\n", m->since); > } > printf("\t */\n"); > printf("\tvoid (*%s)(", m->name); > @@ -1266,6 +1302,9 @@ emit_structs(struct wl_list *message_list, struct > interface *interface, enum sid > printf("};\n\n"); > > if (side == CLIENT) { > + printf("/**\n" > + " * @ingroup %s_iface\n" > + " */\n", interface->name); > printf("static inline int\n" > "%s_add_listener(struct %s *%s,\n" > "%sconst struct %s_listener *listener, void *data)\n" > @@ -1282,34 +1321,6 @@ emit_structs(struct wl_list *message_list, struct > interface *interface, enum sid > } > > static void > -format_copyright(const char *copyright) > -{ > - int bol = 1, start = 0, i, length; > - bool comment_started = false; > - > - length = strlen(copyright); > - for (i = 0; i <= length; i++) { > - if (bol && (copyright[i] == ' ' || copyright[i] == '\t')) { > - continue; > - } else if (bol) { > - bol = 0; > - start = i; > - } > - if (copyright[i] == '\n' || > - (copyright[i] == '\0' && !(start == i))) { > - printf("%s%s%.*s\n", > - comment_started ? " *" : "/*", > - i > start ? " " : "", > - i - start, copyright + start); > - bol = 1; > - comment_started = true; > - } > - } > - if (comment_started) > - printf(" */\n\n"); > -} > - > -static void > emit_types_forward_declarations(struct protocol *protocol, > struct wl_list *message_list, > struct wl_array *types) > @@ -1362,6 +1373,46 @@ get_include_name(bool core, enum side side) > } > > static void > +emit_mainpage_blurb(const struct protocol *protocol, enum side side) > +{ > + struct interface *i; > + > + printf("/**\n" > + " * @page page_%s The %s protocol\n", > + protocol->name, protocol->name); > + > + if (protocol->description) { > + if (protocol->description->summary) { > + printf(" * %s\n" > + " *\n", protocol->description->summary); > + } > + > + if (protocol->description->text) { > + printf(" * @section page_desc_%s Description\n", > protocol->name); > + format_text_to_comment(protocol->description->text, > false); > + printf(" *\n"); > + } > + } > + > + printf(" * @section page_ifaces_%s Interfaces\n", protocol->name); > + wl_list_for_each(i, &protocol->interface_list, link) { > + printf(" * - @subpage page_iface_%s - %s\n", > + i->name, > + i->description && i->description->summary ? > i->description->summary : ""); > + } > + > + if (protocol->copyright) { > + printf(" * @section page_copyright_%s Copyright\n", > + protocol->name); > + printf(" * <pre>\n"); > + format_text_to_comment(protocol->copyright, false); > + printf(" * </pre>\n"); > + } > + > + printf(" */\n"); > +} > + > +static void > emit_header(struct protocol *protocol, enum side side) > { > struct interface *i, *i_next; > @@ -1369,9 +1420,6 @@ emit_header(struct protocol *protocol, enum side side) > const char *s = (side == SERVER) ? "SERVER" : "CLIENT"; > char **p, *prev; > > - if (protocol->copyright) > - format_copyright(protocol->copyright); > - > printf("#ifndef %s_%s_PROTOCOL_H\n" > "#define %s_%s_PROTOCOL_H\n" > "\n" > @@ -1388,6 +1436,8 @@ emit_header(struct protocol *protocol, enum side side) > protocol->uppercase_name, s, > get_include_name(protocol->core_headers, side)); > > + emit_mainpage_blurb(protocol, side); > + > wl_array_init(&types); > wl_list_for_each(i, &protocol->interface_list, link) { > emit_types_forward_declarations(protocol, &i->request_list, > &types); > @@ -1411,6 +1461,24 @@ emit_header(struct protocol *protocol, enum side side) > printf("\n"); > > wl_list_for_each(i, &protocol->interface_list, link) { > + printf("/**\n" > + " * @page page_iface_%s %s\n", > + i->name, i->name); > + if (i->description && i->description->text) { > + printf(" * @section page_iface_%s_desc Description\n", > + i->name); > + format_text_to_comment(i->description->text, false); > + } > + printf(" * @section page_iface_%s_api API\n" > + " * See @ref iface_%s.\n" > + " */\n", > + i->name, i->name); > + printf("/**\n" > + " * @defgroup iface_%s The %s interface\n", > + i->name, i->name); > + if (i->description && i->description->text) > + format_text_to_comment(i->description->text, false); > + printf(" */\n"); > printf("extern const struct wl_interface " > "%s_interface;\n", i->name); > } > @@ -1554,7 +1622,7 @@ emit_code(struct protocol *protocol) > char **p, *prev; > > if (protocol->copyright) > - format_copyright(protocol->copyright); > + format_text_to_comment(protocol->copyright, true); > > printf("#include <stdlib.h>\n" > "#include <stdint.h>\n" > -- > 2.5.0 _______________________________________________ wayland-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/wayland-devel
