[PATCH v2 libevdev 13/13] Add ld version-script

Peter Hutterer peter.hutterer at who-t.net
Sun Aug 25 16:27:33 PDT 2013


From: David Herrmann <dh.herrmann at gmail.com>

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).

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>
Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
Changes to v1:
- rename EXPORT to LIBEVDEV_EXPORT
- remove the previously dropped deprecated functions

 libevdev/Makefile.am    |  9 +++--
 libevdev/libevdev-int.h |  1 +
 libevdev/libevdev.c     | 90 ++++++++++++++++++++++++++-----------------------
 libevdev/libevdev.sym   | 87 +++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 142 insertions(+), 45 deletions(-)
 create mode 100644 libevdev/libevdev.sym

diff --git a/libevdev/Makefile.am b/libevdev/Makefile.am
index 3a67464..073b68e 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
 	        $(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 8ab20e2..b8752ef 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 LIBEVDEV_EXPORT __attribute__((visibility("default")))
 
 #undef min
 #undef max
diff --git a/libevdev/libevdev.c b/libevdev/libevdev.c
index 0a3081e..11dbf23 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*
+LIBEVDEV_EXPORT struct libevdev*
 libevdev_new(void)
 {
 	struct libevdev *dev;
@@ -82,7 +82,7 @@ libevdev_new(void)
 	return dev;
 }
 
-int
+LIBEVDEV_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
+LIBEVDEV_EXPORT void
 libevdev_free(struct libevdev *dev)
 {
 	if (!dev)
@@ -113,7 +113,7 @@ libevdev_free(struct libevdev *dev)
 	free(dev);
 }
 
-void
+LIBEVDEV_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
+LIBEVDEV_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
+LIBEVDEV_EXPORT int
 libevdev_set_fd(struct libevdev* dev, int fd)
 {
 	int rc;
@@ -275,7 +275,7 @@ out:
 	return rc ? -errno : 0;
 }
 
-int
+LIBEVDEV_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)
+LIBEVDEV_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)
+LIBEVDEV_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 *
+LIBEVDEV_EXPORT const char *
 libevdev_get_name(const struct libevdev *dev)
 {
 	return dev->name ? dev->name : "";
 }
 
-const char *
+LIBEVDEV_EXPORT const char *
 libevdev_get_phys(const struct libevdev *dev)
 {
 	return dev->phys;
 }
 
-const char *
+LIBEVDEV_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) \
+LIBEVDEV_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) \
-int libevdev_get_id_##name(const struct libevdev *dev) \
+LIBEVDEV_EXPORT int libevdev_get_id_##name(const struct libevdev *dev) \
 { \
 	return dev->ids.name; \
 }
@@ -688,7 +690,7 @@ PRODUCT_GETTER(bustype);
 PRODUCT_GETTER(version);
 
 #define PRODUCT_SETTER(field) \
-void libevdev_set_id_##field(struct libevdev *dev, int field) \
+LIBEVDEV_EXPORT void libevdev_set_id_##field(struct libevdev *dev, int field) \
 { \
 	dev->ids.field = field;\
 }
@@ -698,18 +700,19 @@ PRODUCT_SETTER(vendor);
 PRODUCT_SETTER(bustype);
 PRODUCT_SETTER(version);
 
-int libevdev_get_driver_version(const struct libevdev *dev)
+LIBEVDEV_EXPORT int
+libevdev_get_driver_version(const struct libevdev *dev)
 {
 	return dev->driver_version;
 }
 
-int
+LIBEVDEV_EXPORT int
 libevdev_has_property(const struct libevdev *dev, unsigned int prop)
 {
 	return (prop <= INPUT_PROP_MAX) && bit_is_set(dev->props, prop);
 }
 
-int
+LIBEVDEV_EXPORT int
 libevdev_enable_property(struct libevdev *dev, unsigned int prop)
 {
 	if (prop > INPUT_PROP_MAX)
@@ -719,13 +722,13 @@ libevdev_enable_property(struct libevdev *dev, unsigned int prop)
 	return 0;
 }
 
-int
+LIBEVDEV_EXPORT int
 libevdev_has_event_type(const struct libevdev *dev, unsigned int type)
 {
 	return (type <= EV_MAX) && bit_is_set(dev->bits, type);
 }
 
-int
+LIBEVDEV_EXPORT int
 libevdev_has_event_code(const struct libevdev *dev, unsigned int type, unsigned int code)
 {
 	const unsigned long *mask;
@@ -745,7 +748,7 @@ libevdev_has_event_code(const struct libevdev *dev, unsigned int type, unsigned
 	return bit_is_set(mask, code);
 }
 
-int
+LIBEVDEV_EXPORT int
 libevdev_get_event_value(const struct libevdev *dev, unsigned int type, unsigned int code)
 {
 	int value;
@@ -764,7 +767,7 @@ libevdev_get_event_value(const struct libevdev *dev, unsigned int type, unsigned
 	return value;
 }
 
-int
+LIBEVDEV_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) &&
@@ -775,7 +778,7 @@ libevdev_fetch_event_value(const struct libevdev *dev, unsigned int type, unsign
 		return 0;
 }
 
-int
+LIBEVDEV_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))
@@ -790,7 +793,7 @@ libevdev_get_slot_value(const struct libevdev *dev, unsigned int slot, unsigned
 	return dev->mt_slot_vals[slot][code - ABS_MT_MIN];
 }
 
-int
+LIBEVDEV_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) &&
@@ -803,19 +806,19 @@ libevdev_fetch_slot_value(const struct libevdev *dev, unsigned int slot, unsigne
 		return 0;
 }
 
-int
+LIBEVDEV_EXPORT int
 libevdev_get_num_slots(const struct libevdev *dev)
 {
 	return dev->num_slots;
 }
 
-int
+LIBEVDEV_EXPORT int
 libevdev_get_current_slot(const struct libevdev *dev)
 {
 	return dev->current_slot;
 }
 
-const struct input_absinfo*
+LIBEVDEV_EXPORT const struct input_absinfo*
 libevdev_get_abs_info(const struct libevdev *dev, unsigned int code)
 {
 	if (!libevdev_has_event_type(dev, EV_ABS) ||
@@ -826,7 +829,7 @@ libevdev_get_abs_info(const struct libevdev *dev, unsigned int code)
 }
 
 #define ABS_GETTER(name) \
-int libevdev_get_abs_##name(const struct libevdev *dev, unsigned int code) \
+LIBEVDEV_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->name : 0; \
@@ -839,7 +842,7 @@ ABS_GETTER(flat);
 ABS_GETTER(resolution);
 
 #define ABS_SETTER(field) \
-void libevdev_set_abs_##field(struct libevdev *dev, unsigned int code, int val) \
+LIBEVDEV_EXPORT void libevdev_set_abs_##field(struct libevdev *dev, unsigned int code, int val) \
 { \
 	if (!libevdev_has_event_code(dev, EV_ABS, code)) \
 		return; \
@@ -852,7 +855,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)
+LIBEVDEV_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;
@@ -860,7 +864,7 @@ void libevdev_set_abs_info(struct libevdev *dev, unsigned int code, const struct
 	dev->abs_info[code] = *abs;
 }
 
-int
+LIBEVDEV_EXPORT int
 libevdev_enable_event_type(struct libevdev *dev, unsigned int type)
 {
 	if (type > EV_MAX)
@@ -879,7 +883,7 @@ libevdev_enable_event_type(struct libevdev *dev, unsigned int type)
 	return 0;
 }
 
-int
+LIBEVDEV_EXPORT int
 libevdev_disable_event_type(struct libevdev *dev, unsigned int type)
 {
 	if (type > EV_MAX || type == EV_SYN)
@@ -890,7 +894,7 @@ libevdev_disable_event_type(struct libevdev *dev, unsigned int type)
 	return 0;
 }
 
-int
+LIBEVDEV_EXPORT int
 libevdev_enable_event_code(struct libevdev *dev, unsigned int type,
 			   unsigned int code, const void *data)
 {
@@ -932,7 +936,7 @@ libevdev_enable_event_code(struct libevdev *dev, unsigned int type,
 	return 0;
 }
 
-int
+LIBEVDEV_EXPORT int
 libevdev_disable_event_code(struct libevdev *dev, unsigned int type, unsigned int code)
 {
 	unsigned int max;
@@ -951,7 +955,7 @@ libevdev_disable_event_code(struct libevdev *dev, unsigned int type, unsigned in
 	return 0;
 }
 
-int
+LIBEVDEV_EXPORT int
 libevdev_kernel_set_abs_value(struct libevdev *dev, unsigned int code, const struct input_absinfo *abs)
 {
 	int rc;
@@ -968,7 +972,7 @@ libevdev_kernel_set_abs_value(struct libevdev *dev, unsigned int code, const str
 	return rc;
 }
 
-int
+LIBEVDEV_EXPORT int
 libevdev_grab(struct libevdev *dev, int grab)
 {
 	int rc = 0;
@@ -990,13 +994,13 @@ libevdev_grab(struct libevdev *dev, int grab)
 	return rc < 0 ? -errno : 0;
 }
 
-int
+LIBEVDEV_EXPORT int
 libevdev_is_event_type(const struct input_event *ev, unsigned int type)
 {
 	return type < EV_MAX && ev->type == type;
 }
 
-int
+LIBEVDEV_EXPORT int
 libevdev_is_event_code(const struct input_event *ev, unsigned int type, unsigned int code)
 {
 	int max;
@@ -1008,7 +1012,7 @@ libevdev_is_event_code(const struct input_event *ev, unsigned int type, unsigned
 	return (max > -1 && code <= (unsigned int)max && ev->code == code);
 }
 
-const char*
+LIBEVDEV_EXPORT const char*
 libevdev_get_event_type_name(unsigned int type)
 {
 	if (type > EV_MAX)
@@ -1017,7 +1021,7 @@ libevdev_get_event_type_name(unsigned int type)
 	return ev_map[type];
 }
 
-const char*
+LIBEVDEV_EXPORT const char*
 libevdev_get_event_code_name(unsigned int type, unsigned int code)
 {
 	int max = libevdev_get_event_type_max(type);
@@ -1028,7 +1032,7 @@ libevdev_get_event_code_name(unsigned int type, unsigned int code)
 	return event_type_map[type][code];
 }
 
-const char*
+LIBEVDEV_EXPORT const char*
 libevdev_get_property_name(unsigned int prop)
 {
 	if (prop > INPUT_PROP_MAX)
@@ -1037,7 +1041,7 @@ libevdev_get_property_name(unsigned int prop)
 	return input_prop_map[prop];
 }
 
-int
+LIBEVDEV_EXPORT int
 libevdev_get_event_type_max(unsigned int type)
 {
 	if (type > EV_MAX)
@@ -1046,7 +1050,7 @@ libevdev_get_event_type_max(unsigned int type)
 	return ev_max[type];
 }
 
-int
+LIBEVDEV_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..8ddf230
--- /dev/null
+++ b/libevdev/libevdev.sym
@@ -0,0 +1,87 @@
+/*
+ * 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;
+
+local:
+	*;
+};
-- 
1.8.2.1



More information about the Input-tools mailing list