Improve consistency of the symbol visibility

To avoid a symbols file on Windows, Epoxy annotates all the publicly
visible symbols directly in the source, but uses the default symbol
visibility everywhere else. This means that only some symbols are
annotated as `EPOXY_IMPORTEXPORT`, and generally only on Windows.
Additionally, Epoxy has a private 'PUBLIC' pre-processor macro for
internal use, which duplicates the `EPOXY_IMPORTEXPORT` but contains
more logic to detect GCC, in case we're building with GCC on Windows.

This would be enough, except that EGL is also available on Windows,
which means we'd have to annotate the exported `epoxy_*` API inside
epoxy/egl.h as well. At that point, though, we should probably avoid
any confusion, and adopt a single symbol visibility policy across the
board.

This requires some surgery of the generated and common dispatch sources,
but cuts down the overall complexity:

 - there is only one annotation, `EPOXY_PUBLIC`, used everywhere
 - the annotation detection is done at Epoxy configuration time
 - only annotated symbols are public, on every platform
 - annotated symbols are immediately visible from the header
macos/v1.5.9
Emmanuele Bassi 8 years ago
parent 0625a74d69
commit 7a06803465
  1. 52
      configure.ac
  2. 4
      include/epoxy/common.h
  3. 4
      include/epoxy/egl.h
  4. 11
      include/epoxy/gl.h
  5. 4
      include/epoxy/glx.h
  6. 4
      include/epoxy/wgl.h
  7. 17
      meson.build
  8. 10
      src/dispatch_common.c
  9. 16
      src/dispatch_common.h
  10. 4
      src/dispatch_egl.c
  11. 4
      src/dispatch_glx.c
  12. 12
      src/dispatch_wgl.c
  13. 16
      src/gen_dispatch.py
  14. 2
      src/meson.build

@ -125,25 +125,39 @@ AM_CONDITIONAL(HAS_GLES1, test x$has_gles1 = xyes)
AC_CHECK_LIB([dl], [dlopen], [DLOPEN_LIBS="-ldl"]) AC_CHECK_LIB([dl], [dlopen], [DLOPEN_LIBS="-ldl"])
AC_SUBST([DLOPEN_LIBS]) AC_SUBST([DLOPEN_LIBS])
case $host_os in VISIBILITY_CFLAGS=""
mingw*) AS_CASE(["$host"],
# visibility flags aren't supported for windows DLLs, and the
# compiler whines to tell you so, so don't set them up. [*-*-mingw*], [
;; dnl on mingw32 we do -fvisibility=hidden and __declspec(dllexport)
*) AC_DEFINE([EPOXY_PUBLIC],
if test "x$GCC" = xyes; then [__attribute__((visibility("default"))) __declspec(dllexport) extern],
save_CFLAGS="$CFLAGS" [defines how to decorate public symbols while building])
AC_MSG_CHECKING([whether $CC supports -fvisibility=hidden]) VISIBILITY_CFLAGS="-fvisibility=hidden"
VISIBILITY_CFLAGS="-fvisibility=hidden" ],
CFLAGS="$CFLAGS $VISIBILITY_CFLAGS"
AC_LINK_IFELSE([AC_LANG_PROGRAM()], AC_MSG_RESULT([yes]), [
[VISIBILITY_CFLAGS=""; AC_MSG_RESULT([no])]); dnl on other compilers, check if we can do -fvisibility=hidden
SAVED_CFLAGS="${CFLAGS}"
# Restore CFLAGS; VISIBILITY_CFLAGS are added to it where needed. CFLAGS="-fvisibility=hidden"
CFLAGS=$save_CFLAGS AC_MSG_CHECKING([for -fvisibility=hidden compiler flag])
fi AC_TRY_COMPILE([], [int main (void) { return 0; }], [
;; AC_MSG_RESULT(yes)
esac enable_fvisibility_hidden=yes
], [
AC_MSG_RESULT(no)
enable_fvisibility_hidden=no
])
CFLAGS="${SAVED_CFLAGS}"
AS_IF([test "${enable_fvisibility_hidden}" = "yes"], [
AC_DEFINE([EPOXY_PUBLIC],
[__attribute__((visibility("default"))) extern],
[defines how to decorate public symbols while building])
VISIBILITY_CFLAGS="-fvisibility=hidden"
])
]
)
AC_SUBST([VISIBILITY_CFLAGS]) AC_SUBST([VISIBILITY_CFLAGS])

@ -37,4 +37,8 @@
# define EPOXY_END_DECLS # define EPOXY_END_DECLS
#endif #endif
#ifndef EPOXY_PUBLIC
# define EPOXY_PUBLIC extern
#endif
#endif /* EPOXY_COMMON_H */ #endif /* EPOXY_COMMON_H */

@ -45,8 +45,8 @@
EPOXY_BEGIN_DECLS EPOXY_BEGIN_DECLS
bool epoxy_has_egl_extension(EGLDisplay dpy, const char *extension); EPOXY_PUBLIC bool epoxy_has_egl_extension(EGLDisplay dpy, const char *extension);
int epoxy_egl_version(EGLDisplay dpy); EPOXY_PUBLIC int epoxy_egl_version(EGLDisplay dpy);
EPOXY_END_DECLS EPOXY_END_DECLS

@ -49,7 +49,6 @@
/* APIENTRY and GLAPIENTRY are not used on Linux or Mac. */ /* APIENTRY and GLAPIENTRY are not used on Linux or Mac. */
#define APIENTRY #define APIENTRY
#define GLAPIENTRY #define GLAPIENTRY
#define EPOXY_IMPORTEXPORT
#define EPOXY_CALLSPEC #define EPOXY_CALLSPEC
#define GLAPI #define GLAPI
#define KHRONOS_APIENTRY #define KHRONOS_APIENTRY
@ -68,10 +67,6 @@
#define EPOXY_CALLSPEC __stdcall #define EPOXY_CALLSPEC __stdcall
#endif #endif
#ifndef EPOXY_IMPORTEXPORT
#define EPOXY_IMPORTEXPORT __declspec(dllimport)
#endif
#ifndef GLAPI #ifndef GLAPI
#define GLAPI extern #define GLAPI extern
#endif #endif
@ -93,9 +88,9 @@
EPOXY_BEGIN_DECLS EPOXY_BEGIN_DECLS
EPOXY_IMPORTEXPORT bool epoxy_has_gl_extension(const char *extension); EPOXY_PUBLIC bool epoxy_has_gl_extension(const char *extension);
EPOXY_IMPORTEXPORT bool epoxy_is_desktop_gl(void); EPOXY_PUBLIC bool epoxy_is_desktop_gl(void);
EPOXY_IMPORTEXPORT int epoxy_gl_version(void); EPOXY_PUBLIC int epoxy_gl_version(void);
EPOXY_END_DECLS EPOXY_END_DECLS

@ -47,8 +47,8 @@
EPOXY_BEGIN_DECLS EPOXY_BEGIN_DECLS
bool epoxy_has_glx_extension(Display *dpy, int screen, const char *extension); EPOXY_PUBLIC bool epoxy_has_glx_extension(Display *dpy, int screen, const char *extension);
int epoxy_glx_version(Display *dpy, int screen); EPOXY_PUBLIC int epoxy_glx_version(Display *dpy, int screen);
EPOXY_END_DECLS EPOXY_END_DECLS

@ -54,8 +54,8 @@
EPOXY_BEGIN_DECLS EPOXY_BEGIN_DECLS
EPOXY_IMPORTEXPORT bool epoxy_has_wgl_extension(HDC hdc, const char *extension); EPOXY_PUBLIC bool epoxy_has_wgl_extension(HDC hdc, const char *extension);
EPOXY_IMPORTEXPORT void epoxy_handle_external_wglMakeCurrent(void); EPOXY_PUBLIC void epoxy_handle_external_wglMakeCurrent(void);
EPOXY_END_DECLS EPOXY_END_DECLS

@ -91,6 +91,23 @@ foreach cflag: test_cflags
endif endif
endforeach endforeach
# Visibility compiler flags
visibility_cflags = []
if get_option('default_library') != 'static'
if host_system == 'windows'
conf.set('DLL_EXPORT', true)
if cc.get_id() == 'msvc'
conf.set('EPOXY_PUBLIC', '__declspec(dllexport) extern')
else
conf.set('EPOXY_PUBLIC', '__attribute__((visibility("default"))) __declspec(dllexport) extern')
visibility_cflags += [ '-fvisibility=hidden' ]
endif
else
conf.set('EPOXY_PUBLIC', '__attribute__((visibility("default")))')
visibility_cflags += [ '-fvisibility=hidden' ]
endif
endif
# Dependencies # Dependencies
dl_dep = cc.find_library('dl', required: false) dl_dep = cc.find_library('dl', required: false)
gl_dep = dependency('gl', required: false) gl_dep = dependency('gl', required: false)

@ -269,7 +269,7 @@ do_dlsym(void **handle, const char *lib_name, const char *name,
return result; return result;
} }
PUBLIC bool bool
epoxy_is_desktop_gl(void) epoxy_is_desktop_gl(void)
{ {
const char *es_prefix = "OpenGL ES"; const char *es_prefix = "OpenGL ES";
@ -333,7 +333,7 @@ epoxy_internal_gl_version(int error_version)
return 10 * major + minor; return 10 * major + minor;
} }
PUBLIC int int
epoxy_gl_version(void) epoxy_gl_version(void)
{ {
return epoxy_internal_gl_version(0); return epoxy_internal_gl_version(0);
@ -459,7 +459,7 @@ epoxy_current_context_is_glx(void)
* \sa epoxy_has_egl_extension() * \sa epoxy_has_egl_extension()
* \sa epoxy_has_glx_extension() * \sa epoxy_has_glx_extension()
*/ */
PUBLIC bool bool
epoxy_has_gl_extension(const char *ext) epoxy_has_gl_extension(const char *ext)
{ {
return epoxy_internal_has_gl_extension(ext, false); return epoxy_internal_has_gl_extension(ext, false);
@ -698,5 +698,5 @@ WRAPPER(epoxy_glEnd)(void)
#endif #endif
} }
PUBLIC PFNGLBEGINPROC epoxy_glBegin = epoxy_glBegin_wrapped; PFNGLBEGINPROC epoxy_glBegin = epoxy_glBegin_wrapped;
PUBLIC PFNGLENDPROC epoxy_glEnd = epoxy_glEnd_wrapped; PFNGLENDPROC epoxy_glEnd = epoxy_glEnd_wrapped;

@ -21,28 +21,26 @@
* IN THE SOFTWARE. * IN THE SOFTWARE.
*/ */
#include "config.h"
#include <stdbool.h> #include <stdbool.h>
#ifdef _WIN32 #ifdef _WIN32
#define PLATFORM_HAS_EGL 0 #define PLATFORM_HAS_EGL 0
#define PLATFORM_HAS_GLX 0 #define PLATFORM_HAS_GLX 0
#define PLATFORM_HAS_WGL 1 #define PLATFORM_HAS_WGL 1
#define EPOXY_IMPORTEXPORT __declspec(dllexport)
#elif defined(__APPLE__) #elif defined(__APPLE__)
#define PLATFORM_HAS_EGL 0 #define PLATFORM_HAS_EGL 0
#define PLATFORM_HAS_GLX 0 #define PLATFORM_HAS_GLX 0
#define PLATFORM_HAS_WGL 0 #define PLATFORM_HAS_WGL 0
#define EPOXY_IMPORTEXPORT
#elif defined(ANDROID) #elif defined(ANDROID)
#define PLATFORM_HAS_EGL 1 #define PLATFORM_HAS_EGL 1
#define PLATFORM_HAS_GLX 0 #define PLATFORM_HAS_GLX 0
#define PLATFORM_HAS_WGL 0 #define PLATFORM_HAS_WGL 0
#define EPOXY_IMPORTEXPORT
#else #else
#define PLATFORM_HAS_EGL 1 #define PLATFORM_HAS_EGL 1
#define PLATFORM_HAS_GLX 1 #define PLATFORM_HAS_GLX 1
#define PLATFORM_HAS_WGL 0 #define PLATFORM_HAS_WGL 0
#define EPOXY_IMPORTEXPORT
#endif #endif
#include "epoxy/gl.h" #include "epoxy/gl.h"
@ -56,16 +54,6 @@
#include "epoxy/wgl.h" #include "epoxy/wgl.h"
#endif #endif
#ifndef PUBLIC
# ifdef _WIN32
# define PUBLIC __declspec(dllexport)
# elif (defined(__GNUC__) && __GNUC__ >= 4) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590))
# define PUBLIC __attribute__((visibility("default")))
# else
# define PUBLIC
# endif
#endif
#if defined(__GNUC__) #if defined(__GNUC__)
#define PACKED __attribute__((__packed__)) #define PACKED __attribute__((__packed__))
#define ENDPACKED #define ENDPACKED

@ -38,7 +38,7 @@ epoxy_conservative_egl_version(void)
return epoxy_egl_version(dpy); return epoxy_egl_version(dpy);
} }
PUBLIC int int
epoxy_egl_version(EGLDisplay dpy) epoxy_egl_version(EGLDisplay dpy)
{ {
int major, minor; int major, minor;
@ -57,7 +57,7 @@ epoxy_conservative_has_egl_extension(const char *ext)
return epoxy_has_egl_extension(eglGetCurrentDisplay(), ext); return epoxy_has_egl_extension(eglGetCurrentDisplay(), ext);
} }
PUBLIC bool bool
epoxy_has_egl_extension(EGLDisplay dpy, const char *ext) epoxy_has_egl_extension(EGLDisplay dpy, const char *ext)
{ {
return epoxy_extension_in_string(eglQueryString(dpy, EGL_EXTENSIONS), ext) || epoxy_extension_in_string(eglQueryString(NULL, EGL_EXTENSIONS), ext); return epoxy_extension_in_string(eglQueryString(dpy, EGL_EXTENSIONS), ext) || epoxy_extension_in_string(eglQueryString(NULL, EGL_EXTENSIONS), ext);

@ -47,7 +47,7 @@ epoxy_conservative_glx_version(void)
return epoxy_glx_version(dpy, screen); return epoxy_glx_version(dpy, screen);
} }
PUBLIC int int
epoxy_glx_version(Display *dpy, int screen) epoxy_glx_version(Display *dpy, int screen)
{ {
int server_major, server_minor; int server_major, server_minor;
@ -98,7 +98,7 @@ epoxy_conservative_has_glx_extension(const char *ext)
return epoxy_has_glx_extension(dpy, screen, ext); return epoxy_has_glx_extension(dpy, screen, ext);
} }
PUBLIC bool bool
epoxy_has_glx_extension(Display *dpy, int screen, const char *ext) epoxy_has_glx_extension(Display *dpy, int screen, const char *ext)
{ {
/* No, you can't just use glXGetClientString or /* No, you can't just use glXGetClientString or

@ -46,7 +46,7 @@ epoxy_conservative_has_wgl_extension(const char *ext)
return epoxy_has_wgl_extension(hdc, ext); return epoxy_has_wgl_extension(hdc, ext);
} }
PUBLIC bool bool
epoxy_has_wgl_extension(HDC hdc, const char *ext) epoxy_has_wgl_extension(HDC hdc, const char *ext)
{ {
PFNWGLGETEXTENSIONSSTRINGARBPROC getext; PFNWGLGETEXTENSIONSSTRINGARBPROC getext;
@ -72,7 +72,7 @@ epoxy_has_wgl_extension(HDC hdc, const char *ext)
* table per context and reuse it when the context is made current * table per context and reuse it when the context is made current
* again. * again.
*/ */
PUBLIC void void
epoxy_handle_external_wglMakeCurrent(void) epoxy_handle_external_wglMakeCurrent(void)
{ {
if (!first_context_current) { if (!first_context_current) {
@ -190,7 +190,7 @@ WRAPPER(epoxy_wglMakeAssociatedContextCurrentAMD)(HGLRC hglrc)
return ret; return ret;
} }
PUBLIC PFNWGLMAKECURRENTPROC epoxy_wglMakeCurrent = epoxy_wglMakeCurrent_wrapped; PFNWGLMAKECURRENTPROC epoxy_wglMakeCurrent = epoxy_wglMakeCurrent_wrapped;
PUBLIC PFNWGLMAKECONTEXTCURRENTEXTPROC epoxy_wglMakeContextCurrentEXT = epoxy_wglMakeContextCurrentEXT_wrapped; PFNWGLMAKECONTEXTCURRENTEXTPROC epoxy_wglMakeContextCurrentEXT = epoxy_wglMakeContextCurrentEXT_wrapped;
PUBLIC PFNWGLMAKECONTEXTCURRENTARBPROC epoxy_wglMakeContextCurrentARB = epoxy_wglMakeContextCurrentARB_wrapped; PFNWGLMAKECONTEXTCURRENTARBPROC epoxy_wglMakeContextCurrentARB = epoxy_wglMakeContextCurrentARB_wrapped;
PUBLIC PFNWGLMAKEASSOCIATEDCONTEXTCURRENTAMDPROC epoxy_wglMakeAssociatedContextCurrentEXT = epoxy_wglMakeAssociatedContextCurrentAMD_wrapped; PFNWGLMAKEASSOCIATEDCONTEXTCURRENTAMDPROC epoxy_wglMakeAssociatedContextCurrentEXT = epoxy_wglMakeAssociatedContextCurrentAMD_wrapped;

@ -77,7 +77,7 @@ class GLFunction(object):
self.public = '' self.public = ''
else: else:
self.wrapped_name = name self.wrapped_name = name
self.public = 'PUBLIC ' self.public = 'EPOXY_PUBLIC '
# This is the string of C code for passing through the # This is the string of C code for passing through the
# arguments to the function. # arguments to the function.
@ -483,6 +483,8 @@ class Generator(object):
def write_header(self, file): def write_header(self, file):
self.write_header_header(file) self.write_header_header(file)
self.outln('#include "epoxy/common.h"')
if self.target != "gl": if self.target != "gl":
self.outln('#include "epoxy/gl.h"') self.outln('#include "epoxy/gl.h"')
if self.target == "egl": if self.target == "egl":
@ -527,9 +529,9 @@ class Generator(object):
self.write_function_ptr_typedefs() self.write_function_ptr_typedefs()
for func in self.sorted_functions: for func in self.sorted_functions:
self.outln('extern EPOXY_IMPORTEXPORT {0} (EPOXY_CALLSPEC *epoxy_{1})({2});'.format(func.ret_type, self.outln('EPOXY_PUBLIC {0} (EPOXY_CALLSPEC *epoxy_{1})({2});'.format(func.ret_type,
func.name, func.name,
func.args_decl)) func.args_decl))
self.outln('') self.outln('')
for func in self.sorted_functions: for func in self.sorted_functions:
@ -619,9 +621,7 @@ class Generator(object):
func.args_list)) func.args_list))
def write_function_pointer(self, func): def write_function_pointer(self, func):
self.outln('{0}{1} epoxy_{2} = epoxy_{2}_global_rewrite_ptr;'.format(func.public, self.outln('{0} epoxy_{1} = epoxy_{1}_global_rewrite_ptr;'.format(func.ptr_type, func.wrapped_name))
func.ptr_type,
func.wrapped_name))
self.outln('') self.outln('')
def write_provider_enums(self): def write_provider_enums(self):
@ -751,6 +751,8 @@ class Generator(object):
self.write_copyright_comment_body() self.write_copyright_comment_body()
self.outln(' */') self.outln(' */')
self.outln('') self.outln('')
self.outln('#include "config.h"')
self.outln('')
self.outln('#include <stdlib.h>') self.outln('#include <stdlib.h>')
self.outln('#include <string.h>') self.outln('#include <string.h>')
self.outln('#include <stdio.h>') self.outln('#include <stdio.h>')

@ -103,7 +103,7 @@ if libtype != 'shared'
install: true, install: true,
dependencies: epoxy_deps, dependencies: epoxy_deps,
include_directories: libepoxy_inc, include_directories: libepoxy_inc,
c_args: common_cflags, c_args: common_cflags + visibility_cflags,
link_args: common_ldflags) link_args: common_ldflags)
libepoxy = libepoxy_static libepoxy = libepoxy_static
endif endif

Loading…
Cancel
Save