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_SUBST([DLOPEN_LIBS])
case $host_os in
mingw*)
# visibility flags aren't supported for windows DLLs, and the
# compiler whines to tell you so, so don't set them up.
;;
*)
if test "x$GCC" = xyes; then
save_CFLAGS="$CFLAGS"
AC_MSG_CHECKING([whether $CC supports -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])]);
# Restore CFLAGS; VISIBILITY_CFLAGS are added to it where needed.
CFLAGS=$save_CFLAGS
fi
;;
esac
VISIBILITY_CFLAGS=""
AS_CASE(["$host"],
[*-*-mingw*], [
dnl on mingw32 we do -fvisibility=hidden and __declspec(dllexport)
AC_DEFINE([EPOXY_PUBLIC],
[__attribute__((visibility("default"))) __declspec(dllexport) extern],
[defines how to decorate public symbols while building])
VISIBILITY_CFLAGS="-fvisibility=hidden"
],
[
dnl on other compilers, check if we can do -fvisibility=hidden
SAVED_CFLAGS="${CFLAGS}"
CFLAGS="-fvisibility=hidden"
AC_MSG_CHECKING([for -fvisibility=hidden compiler flag])
AC_TRY_COMPILE([], [int main (void) { return 0; }], [
AC_MSG_RESULT(yes)
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])

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

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

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

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

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

@ -91,6 +91,23 @@ foreach cflag: test_cflags
endif
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
dl_dep = cc.find_library('dl', 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;
}
PUBLIC bool
bool
epoxy_is_desktop_gl(void)
{
const char *es_prefix = "OpenGL ES";
@ -333,7 +333,7 @@ epoxy_internal_gl_version(int error_version)
return 10 * major + minor;
}
PUBLIC int
int
epoxy_gl_version(void)
{
return epoxy_internal_gl_version(0);
@ -459,7 +459,7 @@ epoxy_current_context_is_glx(void)
* \sa epoxy_has_egl_extension()
* \sa epoxy_has_glx_extension()
*/
PUBLIC bool
bool
epoxy_has_gl_extension(const char *ext)
{
return epoxy_internal_has_gl_extension(ext, false);
@ -698,5 +698,5 @@ WRAPPER(epoxy_glEnd)(void)
#endif
}
PUBLIC PFNGLBEGINPROC epoxy_glBegin = epoxy_glBegin_wrapped;
PUBLIC PFNGLENDPROC epoxy_glEnd = epoxy_glEnd_wrapped;
PFNGLBEGINPROC epoxy_glBegin = epoxy_glBegin_wrapped;
PFNGLENDPROC epoxy_glEnd = epoxy_glEnd_wrapped;

@ -21,28 +21,26 @@
* IN THE SOFTWARE.
*/
#include "config.h"
#include <stdbool.h>
#ifdef _WIN32
#define PLATFORM_HAS_EGL 0
#define PLATFORM_HAS_GLX 0
#define PLATFORM_HAS_WGL 1
#define EPOXY_IMPORTEXPORT __declspec(dllexport)
#elif defined(__APPLE__)
#define PLATFORM_HAS_EGL 0
#define PLATFORM_HAS_GLX 0
#define PLATFORM_HAS_WGL 0
#define EPOXY_IMPORTEXPORT
#elif defined(ANDROID)
#define PLATFORM_HAS_EGL 1
#define PLATFORM_HAS_GLX 0
#define PLATFORM_HAS_WGL 0
#define EPOXY_IMPORTEXPORT
#else
#define PLATFORM_HAS_EGL 1
#define PLATFORM_HAS_GLX 1
#define PLATFORM_HAS_WGL 0
#define EPOXY_IMPORTEXPORT
#endif
#include "epoxy/gl.h"
@ -56,16 +54,6 @@
#include "epoxy/wgl.h"
#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__)
#define PACKED __attribute__((__packed__))
#define ENDPACKED

@ -38,7 +38,7 @@ epoxy_conservative_egl_version(void)
return epoxy_egl_version(dpy);
}
PUBLIC int
int
epoxy_egl_version(EGLDisplay dpy)
{
int major, minor;
@ -57,7 +57,7 @@ epoxy_conservative_has_egl_extension(const char *ext)
return epoxy_has_egl_extension(eglGetCurrentDisplay(), ext);
}
PUBLIC bool
bool
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);

@ -47,7 +47,7 @@ epoxy_conservative_glx_version(void)
return epoxy_glx_version(dpy, screen);
}
PUBLIC int
int
epoxy_glx_version(Display *dpy, int screen)
{
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);
}
PUBLIC bool
bool
epoxy_has_glx_extension(Display *dpy, int screen, const char *ext)
{
/* 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);
}
PUBLIC bool
bool
epoxy_has_wgl_extension(HDC hdc, const char *ext)
{
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
* again.
*/
PUBLIC void
void
epoxy_handle_external_wglMakeCurrent(void)
{
if (!first_context_current) {
@ -190,7 +190,7 @@ WRAPPER(epoxy_wglMakeAssociatedContextCurrentAMD)(HGLRC hglrc)
return ret;
}
PUBLIC PFNWGLMAKECURRENTPROC epoxy_wglMakeCurrent = epoxy_wglMakeCurrent_wrapped;
PUBLIC PFNWGLMAKECONTEXTCURRENTEXTPROC epoxy_wglMakeContextCurrentEXT = epoxy_wglMakeContextCurrentEXT_wrapped;
PUBLIC PFNWGLMAKECONTEXTCURRENTARBPROC epoxy_wglMakeContextCurrentARB = epoxy_wglMakeContextCurrentARB_wrapped;
PUBLIC PFNWGLMAKEASSOCIATEDCONTEXTCURRENTAMDPROC epoxy_wglMakeAssociatedContextCurrentEXT = epoxy_wglMakeAssociatedContextCurrentAMD_wrapped;
PFNWGLMAKECURRENTPROC epoxy_wglMakeCurrent = epoxy_wglMakeCurrent_wrapped;
PFNWGLMAKECONTEXTCURRENTEXTPROC epoxy_wglMakeContextCurrentEXT = epoxy_wglMakeContextCurrentEXT_wrapped;
PFNWGLMAKECONTEXTCURRENTARBPROC epoxy_wglMakeContextCurrentARB = epoxy_wglMakeContextCurrentARB_wrapped;
PFNWGLMAKEASSOCIATEDCONTEXTCURRENTAMDPROC epoxy_wglMakeAssociatedContextCurrentEXT = epoxy_wglMakeAssociatedContextCurrentAMD_wrapped;

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

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

Loading…
Cancel
Save