[PATCH 3/7] Add ld version-script

Peter Hutterer peter.hutterer at who-t.net
Thu Aug 22 18:47:05 PDT 2013


On Thu, Aug 22, 2013 at 03:42:49PM +1000, Peter Hutterer wrote:
> On Sat, Aug 17, 2013 at 01:58:15PM +0200, David Herrmann wrote:
> > Explicit symbol versioning allows us to provide multiple versions of
> > incompatible API changes. It is a very common practice in GNU world and
> > avoids the problems occuring if distributions try to ship multiple version
> > of a single DSO.
> > 
> > We currently don't have any incompatibilities, but we need to start
> > versioning right from the beginning to allow for smooth transitions later.
> > 
> > Background information available at:
> >   http://people.redhat.com/drepper/dsohowto.pdf
> > 
> > To see the symbol-versions, use objdump:
> >   objdump -T libevdev/.libs/libevdev.so.1.0.0
> > This can also be used to verify that all 67 symbols are correctly
> > exported (typos in linker-scripts are silently ignored by ld).
> 
> I wonder if we can hook this up with make check somehow to make sure we
> don't push an API/ABI change without the matching updates to the symbol
> versioning script..
> 
> > Note that we cannot mix linker-scripts with -export-* commands so we
> > explicitly have to mark all symbols as visibility=public via EXPORT.
> > 
> > Signed-off-by: David Herrmann <dh.herrmann at gmail.com>
> > ---
> >  libevdev/Makefile.am    |  9 +++--
> >  libevdev/libevdev-int.h |  1 +
> >  libevdev/libevdev.c     | 92 ++++++++++++++++++++++++-----------------------
> >  libevdev/libevdev.sym   | 95 +++++++++++++++++++++++++++++++++++++++++++++++++
> >  4 files changed, 151 insertions(+), 46 deletions(-)
> >  create mode 100644 libevdev/libevdev.sym
> > 
> > diff --git a/libevdev/Makefile.am b/libevdev/Makefile.am
> > index e71b980..bd8e4fe 100644
> > --- a/libevdev/Makefile.am
> > +++ b/libevdev/Makefile.am
> > @@ -8,7 +8,12 @@ libevdev_la_SOURCES = \
> >                     libevdev-util.h \
> >                     libevdev.c
> >  
> > -libevdev_la_LDFLAGS = -version-info $(LIBEVDEV_LT_VERSION) -export-symbols-regex '^libevdev_' $(GCOV_LDFLAGS)
> > +libevdev_la_LDFLAGS = \
> > +	-version-info $(LIBEVDEV_LT_VERSION) \
> > +	-Wl,--version-script="$(srcdir)/libevdev.sym" \
> > +	$(GCOV_LDFLAGS)
> > +
> > +EXTRA_libevdev_la_DEPENDENCIES = $(srcdir)/libevdev.sym
> >  
> >  libevdevincludedir = $(includedir)/libevdev-1.0/libevdev
> >  libevdevinclude_HEADERS = libevdev.h
> > @@ -16,7 +21,7 @@ libevdevinclude_HEADERS = libevdev.h
> >  event-names.h: Makefile make-event-names.py
> >  	$(PYTHON2) $(srcdir)/make-event-names.py --output=c > $@
> >  
> > -EXTRA_DIST = make-event-names.py
> > +EXTRA_DIST = make-event-names.py libevdev.sym
> >  CLEANFILES = event-names.h
> >  BUILT_SOURCES = event-names.h
> >  
> > diff --git a/libevdev/libevdev-int.h b/libevdev/libevdev-int.h
> > index a36be62..7b6df65 100644
> > --- a/libevdev/libevdev-int.h
> > +++ b/libevdev/libevdev-int.h
> > @@ -37,6 +37,7 @@
> >  #define ABS_MT_MIN ABS_MT_SLOT
> >  #define ABS_MT_MAX ABS_MT_TOOL_Y
> >  #define ABS_MT_CNT (ABS_MT_MAX - ABS_MT_MIN + 1)
> > +#define EXPORT __attribute__((visibility("default")))
> 
> libevdev.h is included in other files, so I'd rather have EXPORT namespaced
> to avoid oddness.

urgh, I should have more (or less?) coffee. clearly the first part of
the comment makes no sense, this is an internal header. I'll merge this
locally and rename it to LIBEVDEV_EXPORT (for consistency with
LIBEVDEV_DEPRECATED).

Cheers,
   Peter
 
> >  
> >  #undef min
> >  #undef max
> > diff --git a/libevdev/libevdev.c b/libevdev/libevdev.c
> > index 0d315ec..9f81177 100644
> > --- a/libevdev/libevdev.c
> > +++ b/libevdev/libevdev.c
> > @@ -64,7 +64,7 @@ libevdev_noop_log_func(const char *format, va_list args)
> >  {
> >  }
> >  
> > -struct libevdev*
> > +EXPORT struct libevdev*
> >  libevdev_new(void)
> >  {
> >  	struct libevdev *dev;
> > @@ -82,7 +82,7 @@ libevdev_new(void)
> >  	return dev;
> >  }
> >  
> > -int
> > +EXPORT int
> >  libevdev_new_from_fd(int fd, struct libevdev **dev)
> >  {
> >  	struct libevdev *d;
> > @@ -100,7 +100,7 @@ libevdev_new_from_fd(int fd, struct libevdev **dev)
> >  	return rc;
> >  }
> >  
> > -void
> > +EXPORT void
> >  libevdev_free(struct libevdev *dev)
> >  {
> >  	if (!dev)
> > @@ -113,7 +113,7 @@ libevdev_free(struct libevdev *dev)
> >  	free(dev);
> >  }
> >  
> > -void
> > +EXPORT void
> >  libevdev_set_log_handler(struct libevdev *dev, libevdev_log_func_t logfunc)
> >  {
> >  	if (dev == NULL)
> > @@ -122,7 +122,7 @@ libevdev_set_log_handler(struct libevdev *dev, libevdev_log_func_t logfunc)
> >  	dev->log = logfunc ? logfunc : libevdev_noop_log_func;
> >  }
> >  
> > -int
> > +EXPORT int
> >  libevdev_change_fd(struct libevdev *dev, int fd)
> >  {
> >  	if (dev->fd == -1)
> > @@ -131,7 +131,7 @@ libevdev_change_fd(struct libevdev *dev, int fd)
> >  	return 0;
> >  }
> >  
> > -int
> > +EXPORT int
> >  libevdev_set_fd(struct libevdev* dev, int fd)
> >  {
> >  	int rc;
> > @@ -275,7 +275,7 @@ out:
> >  	return rc ? -errno : 0;
> >  }
> >  
> > -int
> > +EXPORT int
> >  libevdev_get_fd(const struct libevdev* dev)
> >  {
> >  	return dev->fd;
> > @@ -545,7 +545,8 @@ read_more_events(struct libevdev *dev)
> >  	return 0;
> >  }
> >  
> > -int libevdev_next_event(struct libevdev *dev, unsigned int flags, struct input_event *ev)
> > +EXPORT int
> > +libevdev_next_event(struct libevdev *dev, unsigned int flags, struct input_event *ev)
> >  {
> >  	int rc = 0;
> >  
> > @@ -629,7 +630,8 @@ out:
> >  	return rc;
> >  }
> >  
> > -int libevdev_has_event_pending(struct libevdev *dev)
> > +EXPORT int
> > +libevdev_has_event_pending(struct libevdev *dev)
> >  {
> >  	struct pollfd fds = { dev->fd, POLLIN, 0 };
> >  	int rc;
> > @@ -644,26 +646,26 @@ int libevdev_has_event_pending(struct libevdev *dev)
> >  	return (rc >= 0) ? rc : -errno;
> >  }
> >  
> > -const char *
> > +EXPORT const char *
> >  libevdev_get_name(const struct libevdev *dev)
> >  {
> >  	return dev->name ? dev->name : "";
> >  }
> >  
> > -const char *
> > +EXPORT const char *
> >  libevdev_get_phys(const struct libevdev *dev)
> >  {
> >  	return dev->phys;
> >  }
> >  
> > -const char *
> > +EXPORT const char *
> >  libevdev_get_uniq(const struct libevdev *dev)
> >  {
> >  	return dev->uniq;
> >  }
> >  
> >  #define STRING_SETTER(field) \
> > -void libevdev_set_##field(struct libevdev *dev, const char *field) \
> > +EXPORT void libevdev_set_##field(struct libevdev *dev, const char *field) \
> >  { \
> >  	if (field == NULL) \
> >  		return; \
> > @@ -677,7 +679,7 @@ STRING_SETTER(uniq);
> >  
> >  
> >  #define PRODUCT_GETTER(name, field) \
> > -int libevdev_get_##name(const struct libevdev *dev) \
> > +EXPORT int libevdev_get_##name(const struct libevdev *dev) \
> >  { \
> >  	return dev->ids.field; \
> >  }
> > @@ -693,7 +695,7 @@ PRODUCT_GETTER(id_bustype, bustype);
> >  PRODUCT_GETTER(id_version, version);
> >  
> >  #define PRODUCT_SETTER(field) \
> > -void libevdev_set_id_##field(struct libevdev *dev, int field) \
> > +EXPORT void libevdev_set_id_##field(struct libevdev *dev, int field) \
> >  { \
> >  	dev->ids.field = field;\
> >  }
> > @@ -703,18 +705,19 @@ PRODUCT_SETTER(vendor);
> >  PRODUCT_SETTER(bustype);
> >  PRODUCT_SETTER(version);
> >  
> > -int libevdev_get_driver_version(const struct libevdev *dev)
> > +EXPORT int
> > +libevdev_get_driver_version(const struct libevdev *dev)
> >  {
> >  	return dev->driver_version;
> >  }
> >  
> > -int
> > +EXPORT int
> >  libevdev_has_property(const struct libevdev *dev, unsigned int prop)
> >  {
> >  	return (prop <= INPUT_PROP_MAX) && bit_is_set(dev->props, prop);
> >  }
> >  
> > -int
> > +EXPORT int
> >  libevdev_enable_property(struct libevdev *dev, unsigned int prop)
> >  {
> >  	if (prop > INPUT_PROP_MAX)
> > @@ -724,13 +727,13 @@ libevdev_enable_property(struct libevdev *dev, unsigned int prop)
> >  	return 0;
> >  }
> >  
> > -int
> > +EXPORT int
> >  libevdev_has_event_type(const struct libevdev *dev, unsigned int type)
> >  {
> >  	return (type <= EV_MAX) && bit_is_set(dev->bits, type);
> >  }
> >  
> > -int
> > +EXPORT int
> >  libevdev_has_event_code(const struct libevdev *dev, unsigned int type, unsigned int code)
> >  {
> >  	const unsigned long *mask;
> > @@ -750,7 +753,7 @@ libevdev_has_event_code(const struct libevdev *dev, unsigned int type, unsigned
> >  	return bit_is_set(mask, code);
> >  }
> >  
> > -int
> > +EXPORT int
> >  libevdev_get_event_value(const struct libevdev *dev, unsigned int type, unsigned int code)
> >  {
> >  	int value;
> > @@ -769,7 +772,7 @@ libevdev_get_event_value(const struct libevdev *dev, unsigned int type, unsigned
> >  	return value;
> >  }
> >  
> > -int
> > +EXPORT int
> >  libevdev_fetch_event_value(const struct libevdev *dev, unsigned int type, unsigned int code, int *value)
> >  {
> >  	if (libevdev_has_event_type(dev, type) &&
> > @@ -780,7 +783,7 @@ libevdev_fetch_event_value(const struct libevdev *dev, unsigned int type, unsign
> >  		return 0;
> >  }
> >  
> > -int
> > +EXPORT int
> >  libevdev_get_slot_value(const struct libevdev *dev, unsigned int slot, unsigned int code)
> >  {
> >  	if (!libevdev_has_event_type(dev, EV_ABS) || !libevdev_has_event_code(dev, EV_ABS, code))
> > @@ -795,7 +798,7 @@ libevdev_get_slot_value(const struct libevdev *dev, unsigned int slot, unsigned
> >  	return dev->mt_slot_vals[slot][code - ABS_MT_MIN];
> >  }
> >  
> > -int
> > +EXPORT int
> >  libevdev_fetch_slot_value(const struct libevdev *dev, unsigned int slot, unsigned int code, int *value)
> >  {
> >  	if (libevdev_has_event_type(dev, EV_ABS) &&
> > @@ -807,19 +810,19 @@ libevdev_fetch_slot_value(const struct libevdev *dev, unsigned int slot, unsigne
> >  		return 0;
> >  }
> >  
> > -int
> > +EXPORT int
> >  libevdev_get_num_slots(const struct libevdev *dev)
> >  {
> >  	return dev->num_slots;
> >  }
> >  
> > -int
> > +EXPORT int
> >  libevdev_get_current_slot(const struct libevdev *dev)
> >  {
> >  	return dev->current_slot;
> >  }
> >  
> > -const struct input_absinfo*
> > +EXPORT const struct input_absinfo*
> >  libevdev_get_abs_info(const struct libevdev *dev, unsigned int code)
> >  {
> >  	if (!libevdev_has_event_type(dev, EV_ABS) ||
> > @@ -830,7 +833,7 @@ libevdev_get_abs_info(const struct libevdev *dev, unsigned int code)
> >  }
> >  
> >  #define ABS_GETTER(name, field) \
> > -int libevdev_get_abs_##name(const struct libevdev *dev, unsigned int code) \
> > +EXPORT int libevdev_get_abs_##name(const struct libevdev *dev, unsigned int code) \
> >  { \
> >  	const struct input_absinfo *absinfo = libevdev_get_abs_info(dev, code); \
> >  	return absinfo ? absinfo->field : 0; \
> > @@ -845,7 +848,7 @@ ABS_GETTER(flat, flat)
> >  ABS_GETTER(resolution, resolution)
> >  
> >  #define ABS_SETTER(field) \
> > -void libevdev_set_abs_##field(struct libevdev *dev, unsigned int code, int val) \
> > +EXPORT void libevdev_set_abs_##field(struct libevdev *dev, unsigned int code, int val) \
> >  { \
> >  	if (!libevdev_has_event_code(dev, EV_ABS, code)) \
> >  		return; \
> > @@ -858,7 +861,8 @@ ABS_SETTER(fuzz)
> >  ABS_SETTER(flat)
> >  ABS_SETTER(resolution)
> >  
> > -void libevdev_set_abs_info(struct libevdev *dev, unsigned int code, const struct input_absinfo *abs)
> > +EXPORT void
> > +libevdev_set_abs_info(struct libevdev *dev, unsigned int code, const struct input_absinfo *abs)
> >  {
> >  	if (!libevdev_has_event_code(dev, EV_ABS, code))
> >  		return;
> > @@ -866,7 +870,7 @@ void libevdev_set_abs_info(struct libevdev *dev, unsigned int code, const struct
> >  	dev->abs_info[code] = *abs;
> >  }
> >  
> > -int
> > +EXPORT int
> >  libevdev_enable_event_type(struct libevdev *dev, unsigned int type)
> >  {
> >  	if (type > EV_MAX)
> > @@ -885,7 +889,7 @@ libevdev_enable_event_type(struct libevdev *dev, unsigned int type)
> >  	return 0;
> >  }
> >  
> > -int
> > +EXPORT int
> >  libevdev_disable_event_type(struct libevdev *dev, unsigned int type)
> >  {
> >  	if (type > EV_MAX || type == EV_SYN)
> > @@ -896,7 +900,7 @@ libevdev_disable_event_type(struct libevdev *dev, unsigned int type)
> >  	return 0;
> >  }
> >  
> > -int
> > +EXPORT int
> >  libevdev_enable_event_code(struct libevdev *dev, unsigned int type,
> >  			   unsigned int code, const void *data)
> >  {
> > @@ -938,7 +942,7 @@ libevdev_enable_event_code(struct libevdev *dev, unsigned int type,
> >  	return 0;
> >  }
> >  
> > -int
> > +EXPORT int
> >  libevdev_disable_event_code(struct libevdev *dev, unsigned int type, unsigned int code)
> >  {
> >  	unsigned int max;
> > @@ -957,7 +961,7 @@ libevdev_disable_event_code(struct libevdev *dev, unsigned int type, unsigned in
> >  	return 0;
> >  }
> >  
> > -int
> > +EXPORT int
> >  libevdev_kernel_set_abs_value(struct libevdev *dev, unsigned int code, const struct input_absinfo *abs)
> >  {
> >  	int rc;
> > @@ -974,7 +978,7 @@ libevdev_kernel_set_abs_value(struct libevdev *dev, unsigned int code, const str
> >  	return rc;
> >  }
> >  
> > -int
> > +EXPORT int
> >  libevdev_grab(struct libevdev *dev, int grab)
> >  {
> >  	int rc = 0;
> > @@ -996,13 +1000,13 @@ libevdev_grab(struct libevdev *dev, int grab)
> >  	return rc < 0 ? -errno : 0;
> >  }
> >  
> > -int
> > +EXPORT int
> >  libevdev_is_event_type(const struct input_event *ev, unsigned int type)
> >  {
> >  	return type < EV_MAX && ev->type == type;
> >  }
> >  
> > -int
> > +EXPORT int
> >  libevdev_is_event_code(const struct input_event *ev, unsigned int type, unsigned int code)
> >  {
> >  	return type < EV_MAX &&
> > @@ -1011,7 +1015,7 @@ libevdev_is_event_code(const struct input_event *ev, unsigned int type, unsigned
> >  		ev->code == code;
> >  }
> >  
> > -const char*
> > +EXPORT const char*
> >  libevdev_get_event_type_name(unsigned int type)
> >  {
> >  	if (type > EV_MAX)
> > @@ -1020,7 +1024,7 @@ libevdev_get_event_type_name(unsigned int type)
> >  	return ev_map[type];
> >  }
> >  
> > -const char*
> > +EXPORT const char*
> >  libevdev_get_event_code_name(unsigned int type, unsigned int code)
> >  {
> >  	if (type > EV_MAX)
> > @@ -1033,13 +1037,13 @@ libevdev_get_event_code_name(unsigned int type, unsigned int code)
> >  }
> >  
> >  /* DEPRECATED */
> > -const char*
> > +EXPORT const char*
> >  libevdev_get_input_prop_name(unsigned int prop)
> >  {
> >  	return libevdev_get_property_name(prop);
> >  }
> >  
> > -const char*
> > +EXPORT const char*
> >  libevdev_get_property_name(unsigned int prop)
> >  {
> >  	if (prop > INPUT_PROP_MAX)
> > @@ -1048,7 +1052,7 @@ libevdev_get_property_name(unsigned int prop)
> >  	return input_prop_map[prop];
> >  }
> >  
> > -int
> > +EXPORT int
> >  libevdev_get_event_type_max(unsigned int type)
> >  {
> >  	if (type > EV_MAX)
> > @@ -1057,7 +1061,7 @@ libevdev_get_event_type_max(unsigned int type)
> >  	return ev_max[type];
> >  }
> >  
> > -int
> > +EXPORT int
> >  libevdev_get_repeat(struct libevdev *dev, int *delay, int *period)
> >  {
> >  	if (!libevdev_has_event_type(dev, EV_REP))
> > diff --git a/libevdev/libevdev.sym b/libevdev/libevdev.sym
> > new file mode 100644
> > index 0000000..4cf40bb
> > --- /dev/null
> > +++ b/libevdev/libevdev.sym
> > @@ -0,0 +1,95 @@
> > +/*
> > + * Copyright (c) 2013 David Herrmann <dh.herrmann at gmail.com>
> > + *
> > + * Permission to use, copy, modify, distribute, and sell this software and its
> > + * documentation for any purpose is hereby granted without fee, provided that
> > + * the above copyright notice appear in all copies and that both that copyright
> > + * notice and this permission notice appear in supporting documentation, and
> > + * that the name of the copyright holders not be used in advertising or
> > + * publicity pertaining to distribution of the software without specific,
> > + * written prior permission.  The copyright holders make no representations
> > + * about the suitability of this software for any purpose.  It is provided "as
> > + * is" without express or implied warranty.
> > + *
> > + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
> > + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
> > + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
> > + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
> > + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
> > + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
> > + * OF THIS SOFTWARE.
> > + */
> > +
> > +LIBEVDEV_1 {
> > +global:
> > +	libevdev_new;
> > +	libevdev_new_from_fd;
> > +	libevdev_free;
> > +	libevdev_set_log_handler;
> > +	libevdev_grab;
> > +	libevdev_set_fd;
> > +	libevdev_change_fd;
> > +	libevdev_get_fd;
> > +	libevdev_next_event;
> > +	libevdev_has_event_pending;
> > +	libevdev_get_name;
> > +	libevdev_set_name;
> > +	libevdev_get_phys;
> > +	libevdev_set_phys;
> > +	libevdev_get_uniq;
> > +	libevdev_set_uniq;
> > +	libevdev_get_id_product;
> > +	libevdev_set_id_product;
> > +	libevdev_get_id_vendor;
> > +	libevdev_set_id_vendor;
> > +	libevdev_get_id_bustype;
> > +	libevdev_set_id_bustype;
> > +	libevdev_get_id_version;
> > +	libevdev_set_id_version;
> > +	libevdev_get_driver_version;
> > +	libevdev_has_property;
> > +	libevdev_enable_property;
> > +	libevdev_has_event_type;
> > +	libevdev_has_event_code;
> > +	libevdev_get_abs_minimum;
> > +	libevdev_get_abs_maximum;
> > +	libevdev_get_abs_fuzz;
> > +	libevdev_get_abs_flat;
> > +	libevdev_get_abs_resolution;
> > +	libevdev_get_abs_info;
> > +	libevdev_get_event_value;
> > +	libevdev_fetch_event_value;
> > +	libevdev_get_slot_value;
> > +	libevdev_fetch_slot_value;
> > +	libevdev_get_num_slots;
> > +	libevdev_get_current_slot;
> > +	libevdev_set_abs_minimum;
> > +	libevdev_set_abs_maximum;
> > +	libevdev_set_abs_fuzz;
> > +	libevdev_set_abs_flat;
> > +	libevdev_set_abs_resolution;
> > +	libevdev_set_abs_info;
> > +	libevdev_enable_event_type;
> > +	libevdev_disable_event_type;
> > +	libevdev_enable_event_code;
> > +	libevdev_disable_event_code;
> > +	libevdev_kernel_set_abs_value;
> > +	libevdev_is_event_type;
> > +	libevdev_is_event_code;
> > +	libevdev_get_event_type_name;
> > +	libevdev_get_event_code_name;
> > +	libevdev_get_property_name;
> > +	libevdev_get_event_type_max;
> > +	libevdev_get_repeat;
> > +
> > +	/* deprecated */
> > +	libevdev_get_abs_min;
> > +	libevdev_get_abs_max;
> > +	libevdev_get_input_prop_name;
> > +	libevdev_get_product_id;
> > +	libevdev_get_vendor_id;
> > +	libevdev_get_bustype;
> > +	libevdev_get_version;
> > +local:
> > +	*;
> > +};
> > -- 
> > 1.8.3.4
> > 
> _______________________________________________
> Input-tools mailing list
> Input-tools at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/input-tools


More information about the Input-tools mailing list