Add a --visibility flag that enables the user to tweak the visibility
of the symbols generated by wayland-scanner. Three alternatives are
exposed:

'export': as has always been done up until now, export the symbols
using WL_EXPORT, making making them exposed externally. This is the
default in order to not break backward compatibility.

'compiler-default': use whatever visibility the compiler defaults to.
This is most likely the most visibility that protocol implementations
or users actually wants, as it doesn't expose any unwanted
implementation details.

'static': each symbol will only be visible to the compilation unit it
is included in. This means that a protocol implementations and users
needs to include both the 'code' file and either the 'client-header' or
'server-header' (or both) in the source file implementing or using the
protocol in question.

Using 'static' is a method to avoid situations where otherwise exposed
symbols of different protocols would conflict, for example if they have
the same interface name.

When no visibility is specified, 'export' is assumed, but a warning is
printed to stderr, as it is unlikely that 'export' is what is actually
desired.

Signed-off-by: Jonas Ådahl <jad...@gmail.com>
---

Changes since v1:

- Use 'extern' tag also for compiler default declarations.

- "see --help" message to the warning

- Added 'what visibility to choose' kind of documentation to --help


 Makefile.am   |  10 ++---
 src/scanner.c | 135 +++++++++++++++++++++++++++++++++++++++++++++++++++-------
 2 files changed, 125 insertions(+), 20 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index d0c8bd3..d570525 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -97,19 +97,19 @@ nodist_libwayland_client_la_SOURCES =               \
 pkgconfig_DATA += src/wayland-client.pc src/wayland-server.pc
 
 protocol/%-protocol.c : $(top_srcdir)/protocol/%.xml
-       $(AM_V_GEN)$(MKDIR_P) $(dir $@) && $(wayland_scanner) code < $< > $@
+       $(AM_V_GEN)$(MKDIR_P) $(dir $@) && $(wayland_scanner) -Vexport code < 
$< > $@
 
 protocol/%-server-protocol.h : $(top_srcdir)/protocol/%.xml
-       $(AM_V_GEN)$(MKDIR_P) $(dir $@) && $(wayland_scanner) server-header < 
$< > $@
+       $(AM_V_GEN)$(MKDIR_P) $(dir $@) && $(wayland_scanner) -Vexport 
server-header < $< > $@
 
 protocol/%-client-protocol.h : $(top_srcdir)/protocol/%.xml
-       $(AM_V_GEN)$(MKDIR_P) $(dir $@) && $(wayland_scanner) client-header < 
$< > $@
+       $(AM_V_GEN)$(MKDIR_P) $(dir $@) && $(wayland_scanner) -Vexport 
client-header < $< > $@
 
 protocol/%-server-protocol-core.h : $(top_srcdir)/protocol/%.xml
-       $(AM_V_GEN)$(MKDIR_P) $(dir $@) && $(wayland_scanner) server-header -c 
< $< > $@
+       $(AM_V_GEN)$(MKDIR_P) $(dir $@) && $(wayland_scanner) -Vexport 
server-header -c < $< > $@
 
 protocol/%-client-protocol-core.h : $(top_srcdir)/protocol/%.xml
-       $(AM_V_GEN)$(MKDIR_P) $(dir $@) && $(wayland_scanner) client-header -c 
< $< > $@
+       $(AM_V_GEN)$(MKDIR_P) $(dir $@) && $(wayland_scanner) -Vexport 
client-header -c < $< > $@
 
 BUILT_SOURCES =                                        \
        $(nodist_libwayland_server_la_SOURCES)  \
diff --git a/src/scanner.c b/src/scanner.c
index 517068c..3e43f90 100644
--- a/src/scanner.c
+++ b/src/scanner.c
@@ -57,6 +57,12 @@ enum side {
        SERVER,
 };
 
+enum visibility {
+       VISIBILITY_EXPORT,
+       VISIBILITY_COMPILER_DEFAULT,
+       VISIBILITY_STATIC
+};
+
 static int
 usage(int ret)
 {
@@ -72,7 +78,30 @@ usage(int ret)
                        "                                 the scanner was built 
against.\n"
                        "    -c,  --include-core-only     include the core 
version of the headers,\n"
                        "                                 that is e.g. 
wayland-client-core.h instead\n"
-                       "                                 of 
wayland-client.h.\n");
+                       "                                 of 
wayland-client.h.\n"
+                       "    -V,  
--visibility=[export|compiler-default|static]\n"
+                       "                                 select what type of 
visibility protocol\n"
+                       "                                 symbols should have. 
'export' will cause the\n"
+                       "                                 symbols to be 
exported, 'compiler-default'\n"
+                       "                                 will use the compiler 
default (often visible\n"
+                       "                                 only within the same 
DSO), 'static' will make\n"
+                       "                                 all symbols static 
(note that the file\n"
+                       "                                 generated with 'code' 
must be included in the\n"
+                       "                                 same file as the 
symbols are used\n"
+                       "\n"
+                       "                                 When in doubt, use 
'compiler-default' as this\n"
+                       "                                 means no symbols are 
unexpectedly exposed\n"
+                       "                                 externally.\n"
+                       "\n"
+                       "                                 When symbols have 
already been exported, and\n"
+                       "                                 they must continue to 
be, or if you actually\n"
+                       "                                 want to export the 
symbols, use 'export'.\n"
+                       "\n"
+                       "                                 When you need to 
implement two protocols with\n"
+                       "                                 conflicting interface 
names, use 'static' and\n"
+                       "                                 include both the 
header and code in the source\n"
+                       "                                 code file 
implementing or using the protocol\n"
+                       "");
        exit(ret);
 }
 
@@ -226,6 +255,7 @@ struct entry {
 };
 
 struct parse_context {
+       enum visibility visibility;
        struct location loc;
        XML_Parser parser;
        struct protocol *protocol;
@@ -1507,11 +1537,14 @@ emit_mainpage_blurb(const struct protocol *protocol, 
enum side side)
 }
 
 static void
-emit_header(struct protocol *protocol, enum side side)
+emit_header(struct parse_context *ctx,
+           struct protocol *protocol,
+           enum side side)
 {
        struct interface *i, *i_next;
        struct wl_array types;
        const char *s = (side == SERVER) ? "SERVER" : "CLIENT";
+       const char *symbol_decl_tag = NULL;
        char **p, *prev;
 
        printf("/* Generated by %s %s */\n\n", PROGRAM_NAME, WAYLAND_VERSION);
@@ -1556,6 +1589,16 @@ emit_header(struct protocol *protocol, enum side side)
        wl_array_release(&types);
        printf("\n");
 
+       switch (ctx->visibility) {
+       case VISIBILITY_EXPORT:
+       case VISIBILITY_COMPILER_DEFAULT:
+               symbol_decl_tag = "extern ";
+               break;
+       case VISIBILITY_STATIC:
+               symbol_decl_tag = "static ";
+               break;
+       }
+
        wl_list_for_each(i, &protocol->interface_list, link) {
                printf("/**\n"
                       " * @page page_iface_%s %s\n",
@@ -1575,8 +1618,9 @@ emit_header(struct protocol *protocol, enum side side)
                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);
+               printf("%sconst struct wl_interface "
+                      "%s_interface;\n",
+                      symbol_decl_tag, i->name);
        }
 
        printf("\n");
@@ -1713,11 +1757,13 @@ emit_messages(struct wl_list *message_list,
 }
 
 static void
-emit_code(struct protocol *protocol)
+emit_code(struct parse_context *ctx, struct protocol *protocol)
 {
        struct interface *i, *next;
        struct wl_array types;
        char **p, *prev;
+       const char *visibility_tag = NULL;
+       const char *symbol_decl_tag = NULL;
 
        printf("/* Generated by %s %s */\n\n", PROGRAM_NAME, WAYLAND_VERSION);
 
@@ -1728,6 +1774,16 @@ emit_code(struct protocol *protocol)
               "#include <stdint.h>\n"
               "#include \"wayland-util.h\"\n\n");
 
+       switch (ctx->visibility) {
+       case VISIBILITY_EXPORT:
+       case VISIBILITY_COMPILER_DEFAULT:
+               symbol_decl_tag = "extern ";
+               break;
+       case VISIBILITY_STATIC:
+               symbol_decl_tag = "static ";
+               break;
+       }
+
        wl_array_init(&types);
        wl_list_for_each(i, &protocol->interface_list, link) {
                emit_types_forward_declarations(protocol, &i->request_list, 
&types);
@@ -1738,7 +1794,8 @@ emit_code(struct protocol *protocol)
        wl_array_for_each(p, &types) {
                if (prev && strcmp(*p, prev) == 0)
                        continue;
-               printf("extern const struct wl_interface %s_interface;\n", *p);
+               printf("%sconst struct wl_interface %s_interface;\n",
+                      symbol_decl_tag, *p);
                prev = *p;
        }
        wl_array_release(&types);
@@ -1752,14 +1809,26 @@ emit_code(struct protocol *protocol)
        }
        printf("};\n\n");
 
+       switch (ctx->visibility) {
+       case VISIBILITY_EXPORT:
+               visibility_tag = "WL_EXPORT ";
+               break;
+       case VISIBILITY_COMPILER_DEFAULT:
+               visibility_tag = "";
+               break;
+       case VISIBILITY_STATIC:
+               visibility_tag = "static ";
+               break;
+       }
        wl_list_for_each_safe(i, next, &protocol->interface_list, link) {
 
                emit_messages(&i->request_list, i, "requests");
                emit_messages(&i->event_list, i, "events");
 
-               printf("WL_EXPORT const struct wl_interface "
+               printf("%sconst struct wl_interface "
                       "%s_interface = {\n"
                       "\t\"%s\", %d,\n",
+                      visibility_tag,
                       i->name, i->name, i->version);
 
                if (!wl_list_empty(&i->request_list))
@@ -1790,12 +1859,32 @@ free_protocol(struct protocol *protocol)
        free_description(protocol->description);
 }
 
+static int
+parse_visibility_str(const char *visibility_str,
+                    enum visibility *visibility)
+{
+       if (strcmp(visibility_str, "export") == 0) {
+               *visibility = VISIBILITY_EXPORT;
+       } else if (strcmp(visibility_str, "compiler-default") == 0) {
+               *visibility = VISIBILITY_COMPILER_DEFAULT;
+       } else if (strcmp(visibility_str, "static") == 0) {
+               *visibility = VISIBILITY_STATIC;
+       } else {
+               fprintf(stderr, "Error: invalid visibility string '%s'\n",
+                       visibility_str);
+               return -1;
+       }
+
+       return 0;
+}
+
 int main(int argc, char *argv[])
 {
        struct parse_context ctx;
        struct protocol protocol;
        FILE *input = stdin;
        char *input_filename = NULL;
+       char *visibility_str = NULL;
        int len;
        void *buf;
        bool help = false;
@@ -1803,6 +1892,7 @@ int main(int argc, char *argv[])
        bool version = false;
        bool fail = false;
        int opt;
+       enum visibility visibility = 0;
        enum {
                CLIENT_HEADER,
                SERVER_HEADER,
@@ -1810,14 +1900,15 @@ int main(int argc, char *argv[])
        } mode;
 
        static const struct option options[] = {
-               { "help",              no_argument, NULL, 'h' },
-               { "version",           no_argument, NULL, 'v' },
-               { "include-core-only", no_argument, NULL, 'c' },
-               { 0,                   0,           NULL, 0 }
+               { "help",              no_argument,       NULL, 'h' },
+               { "version",           no_argument,       NULL, 'v' },
+               { "include-core-only", no_argument,       NULL, 'c' },
+               { "visibility",        required_argument, NULL, 'V' },
+               { 0,                   0,                 NULL, 0 }
        };
 
        while (1) {
-               opt = getopt_long(argc, argv, "hvc", options, NULL);
+               opt = getopt_long(argc, argv, "hvcV:", options, NULL);
 
                if (opt == -1)
                        break;
@@ -1832,6 +1923,9 @@ int main(int argc, char *argv[])
                case 'c':
                        core_headers = true;
                        break;
+               case 'V':
+                       visibility_str = optarg;
+                       break;
                default:
                        fail = true;
                        break;
@@ -1858,6 +1952,16 @@ int main(int argc, char *argv[])
        else
                usage(EXIT_FAILURE);
 
+       if (!visibility_str) {
+               fprintf(stderr,
+                       "Warning: protocol symbols will be exported, "
+                       "make sure this is desired. See --help for more 
information\n"
+                       "on visibility.\n");
+               visibility = VISIBILITY_EXPORT;
+       } else if (parse_visibility_str(visibility_str, &visibility) != 0) {
+               usage(EXIT_FAILURE);
+       }
+
        if (argc == 3) {
                input_filename = argv[1];
                input = fopen(input_filename, "r");
@@ -1882,6 +1986,7 @@ int main(int argc, char *argv[])
        /* initialize context */
        memset(&ctx, 0, sizeof ctx);
        ctx.protocol = &protocol;
+       ctx.visibility = visibility;
        if (input == stdin)
                ctx.loc.filename = "<stdin>";
        else
@@ -1931,13 +2036,13 @@ int main(int argc, char *argv[])
 
        switch (mode) {
                case CLIENT_HEADER:
-                       emit_header(&protocol, CLIENT);
+                       emit_header(&ctx, &protocol, CLIENT);
                        break;
                case SERVER_HEADER:
-                       emit_header(&protocol, SERVER);
+                       emit_header(&ctx, &protocol, SERVER);
                        break;
                case CODE:
-                       emit_code(&protocol);
+                       emit_code(&ctx, &protocol);
                        break;
        }
 
-- 
2.13.0

_______________________________________________
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to