* guile-dbi: Use libltdl and prefer GUILE_DBD_PATH.
[not found] ` <87fus6mfbe.fsf@gnu.org>
@ 2016-09-16 3:36 ` 宋文武
2016-09-16 6:57 ` baux
2017-07-10 22:54 ` Linas Vepstas
0 siblings, 2 replies; 5+ messages in thread
From: 宋文武 @ 2016-09-16 3:36 UTC (permalink / raw)
To: Maurizio Boriani; +Cc: guix-devel, guile-user
[-- Attachment #1: Type: text/plain, Size: 632 bytes --]
Hi!
To reall, curentlly, guile-dbi use dlopen to load its backends.
So, for Guix we have to set LD_LIBRARY_PATH, which is not desired.
> [...]
> (me:)
>> I think it will be great to introduce a new search path (eg: GUILE_DBD_PATH)
>> in addition to LD_LIBRARY_PATH. Find the absolute so filepath in it
>> ourself, then pass to dlopen.
>
> (ludo:)
> Why not, but then it would be redundant with LD_LIBRARY_PATH and
> LTDL_LIBRARY_PATH, which would further complicate the search rules.
>
Yeah, but I just learn that libltdl has a convenient function to do
this..
So, here are patches for using libltdl and a new search path:
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Use-libltdl-to-dlopen-backends.patch --]
[-- Type: text/x-patch, Size: 5983 bytes --]
From 59d529388d062ddad581bcd7f0c56690a84bf7df Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=AE=8B=E6=96=87=E6=AD=A6?= <iyzsong@gmail.com>
Date: Fri, 16 Sep 2016 10:30:36 +0800
Subject: [PATCH 1/3] Use libltdl to dlopen backends.
* include/guile-dbi/guile-dbi.h (gdbi_db_handle_t): Use 'lt_dlhandle'.
* src/guile-dbi.c: Replace libdl calls with their libltdl equivalences.
* Makefile.am (SUBDIRS): Add libltdl.
* configure.ac: Use LTDL_INIT. Add LTDLINCL and LIBLTDL to flags.
* src/Makefile.am (libguile_dbi_la_LIBDD): Remove '-ldl'.
---
guile-dbi/Makefile.am | 2 +-
guile-dbi/configure.ac | 8 +++++---
guile-dbi/include/guile-dbi/guile-dbi.h | 3 ++-
guile-dbi/src/Makefile.am | 2 +-
guile-dbi/src/guile-dbi.c | 25 ++++++++++---------------
5 files changed, 19 insertions(+), 21 deletions(-)
diff --git a/guile-dbi/Makefile.am b/guile-dbi/Makefile.am
index e4cae61..011740b 100644
--- a/guile-dbi/Makefile.am
+++ b/guile-dbi/Makefile.am
@@ -24,7 +24,7 @@
ACLOCAL_AMFLAGS = -I m4
AUTOMAKE_OPTIONS = gnu
-SUBDIRS = src include doc
+SUBDIRS = libltdl src include doc
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = guile-dbi.pc
diff --git a/guile-dbi/configure.ac b/guile-dbi/configure.ac
index cc45703..d902cb0 100644
--- a/guile-dbi/configure.ac
+++ b/guile-dbi/configure.ac
@@ -55,14 +55,16 @@ AC_CHECK_FUNCS([strerror])
# ltmain needs these:
AC_CONFIG_MACRO_DIR([m4])
-LT_INIT
+LT_INIT([dlopen])
+LT_CONFIG_LTDL_DIR([libltdl])
+LTDL_INIT
# AC_PROG_INSTALL
# AC_PROG_MAKE_SET
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])], [AC_SUBST([AM_DEFAULT_VERBOSITY],1)])
-CFLAGS=`$GUILECONFIG compile`
-LIBS=`$GUILECONFIG link`
+CFLAGS="$LTDLINCL `$GUILECONFIG compile`"
+LIBS="$LIBLTDL `$GUILECONFIG link`"
GUILE_SITE=`$GUILECONFIG info sitedir`
AC_ARG_WITH([guile-site-dir],
diff --git a/guile-dbi/include/guile-dbi/guile-dbi.h b/guile-dbi/include/guile-dbi/guile-dbi.h
index b75d3dc..00449ee 100644
--- a/guile-dbi/include/guile-dbi/guile-dbi.h
+++ b/guile-dbi/include/guile-dbi/guile-dbi.h
@@ -24,6 +24,7 @@
#define __GUILE_DBI_H__
#include <libguile.h>
+#include <ltdl.h>
/* guile smob struct */
typedef struct
@@ -32,7 +33,7 @@ typedef struct
SCM constr;
SCM status; /* pair: car = error numeric code, cdr = status message */
SCM closed; /* boolean, TRUE if closed otherwise FALSE */
- void* handle;
+ lt_dlhandle handle;
void* db_info;
int in_free; /* boolean, used to avoid alloc during garbage collection */
const char * bcknd_str;
diff --git a/guile-dbi/src/Makefile.am b/guile-dbi/src/Makefile.am
index a3001db..0795899 100644
--- a/guile-dbi/src/Makefile.am
+++ b/guile-dbi/src/Makefile.am
@@ -35,7 +35,7 @@ SUFFIXES = .x
lib_LTLIBRARIES = libguile-dbi.la
libguile_dbi_la_SOURCES = guile-dbi.c guile-dbi.x
-libguile_dbi_la_LIBADD = -ldl $(LIBS)
+libguile_dbi_la_LIBADD = $(LIBS)
libguile_dbi_la_LDFLAGS = -export-dynamic -version-info @DBI_INTERFACE@
libguile_dbi_la_DEPENDENCIES = $(LTLIBOBJS)
diff --git a/guile-dbi/src/guile-dbi.c b/guile-dbi/src/guile-dbi.c
index 5d797d9..d4ae040 100644
--- a/guile-dbi/src/guile-dbi.c
+++ b/guile-dbi/src/guile-dbi.c
@@ -24,7 +24,6 @@
#include <guile-dbi/guile-dbi.h>
#include <string.h>
#include <errno.h>
-#include <dlfcn.h>
#include <stdio.h>
@@ -59,9 +58,8 @@ SCM_DEFINE (make_g_db_handle, "dbi-open", 2, 0, 0,
g_db_handle->bcknd_str = scm_to_locale_string (bcknd);
g_db_handle->bcknd_strlen = strlen(g_db_handle->bcknd_str);
- /* The +20 allos for .so or .dylib on MacOS */
sodbd_len = sizeof(char) * (strlen("libguile-dbd-") +
- g_db_handle->bcknd_strlen + 20);
+ g_db_handle->bcknd_strlen + 1);
sodbd = (char*) malloc (sodbd_len);
if (sodbd == NULL)
{
@@ -70,18 +68,14 @@ SCM_DEFINE (make_g_db_handle, "dbi-open", 2, 0, 0,
SCM_RETURN_NEWSMOB (g_db_handle_tag, g_db_handle);
}
-#ifdef __APPLE__
- snprintf(sodbd, sodbd_len, "libguile-dbd-%s.dylib", g_db_handle->bcknd_str);
-#else
- snprintf(sodbd, sodbd_len, "libguile-dbd-%s.so", g_db_handle->bcknd_str);
-#endif
+ snprintf(sodbd, sodbd_len, "libguile-dbd-%s", g_db_handle->bcknd_str);
- g_db_handle->handle = dlopen(sodbd, RTLD_NOW);
+ g_db_handle->handle = lt_dlopenext(sodbd);
if (g_db_handle->handle == NULL)
{
free(sodbd);
g_db_handle->status = scm_cons(scm_from_int(1),
- scm_from_locale_string(dlerror()));
+ scm_from_locale_string(lt_dlerror()));
SCM_RETURN_NEWSMOB (g_db_handle_tag, g_db_handle);
}
@@ -174,7 +168,7 @@ SCM_DEFINE (close_g_db_handle, "dbi-close", 1, 0, 0,
(*dbd_close)(g_db_handle);
if (g_db_handle->handle)
{
- dlclose(g_db_handle->handle);
+ lt_dlclose(g_db_handle->handle);
g_db_handle->handle = NULL;
}
scm_remember_upto_here_1(db_handle);
@@ -311,6 +305,7 @@ init_dbi(void)
if (is_inited) return;
is_inited = 1;
init_db_handle_type();
+ lt_dlinit();
#ifndef SCM_MAGIC_SNARFER
#include "guile-dbi.x"
@@ -324,7 +319,7 @@ void
__gdbi_dbd_wrap(gdbi_db_handle_t* dbh, const char* function_name,
void** function_pointer)
{
- char *ret = NULL;
+ const char *ret = NULL;
char *func = NULL;
size_t func_len;
@@ -340,9 +335,9 @@ __gdbi_dbd_wrap(gdbi_db_handle_t* dbh, const char* function_name,
/* I assume this is correct for all OS'es */
snprintf(func, func_len, "__%s_%s", dbh->bcknd_str, function_name);
- dlerror(); /* Clear any existing error -- Solaris needs this */
- *function_pointer = dlsym(dbh->handle, func);
- if ((ret = dlerror()) != NULL)
+ lt_dlerror(); /* Clear any existing error -- Solaris needs this */
+ *function_pointer = lt_dlsym(dbh->handle, func);
+ if ((ret = lt_dlerror()) != NULL)
{
free(func);
if (dbh->in_free) return; /* do not SCM anything while in GC */
--
2.10.0
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: 0002-Prefer-GUILE_DBD_PATH-as-search-path-for-backends.patch --]
[-- Type: text/x-patch, Size: 887 bytes --]
From 495a47aaf79fd501e793562a340a7528ef587144 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=AE=8B=E6=96=87=E6=AD=A6?= <iyzsong@gmail.com>
Date: Fri, 16 Sep 2016 11:07:59 +0800
Subject: [PATCH 2/3] Prefer GUILE_DBD_PATH as search path for backends.
* src/guile-dbi.c (init_dbi): Call 'lt_dlsetsearchpath'.
---
guile-dbi/src/guile-dbi.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/guile-dbi/src/guile-dbi.c b/guile-dbi/src/guile-dbi.c
index d4ae040..b609a88 100644
--- a/guile-dbi/src/guile-dbi.c
+++ b/guile-dbi/src/guile-dbi.c
@@ -25,6 +25,7 @@
#include <string.h>
#include <errno.h>
#include <stdio.h>
+#include <stdlib.h>
static scm_t_bits g_db_handle_tag;
@@ -306,6 +307,7 @@ init_dbi(void)
is_inited = 1;
init_db_handle_type();
lt_dlinit();
+ lt_dlsetsearchpath(getenv("GUILE_DBD_PATH"));
#ifndef SCM_MAGIC_SNARFER
#include "guile-dbi.x"
--
2.10.0
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #4: 0003-Update-documentation-for-the-usage-of-libltdl.patch --]
[-- Type: text/x-patch, Size: 2889 bytes --]
From 1a2fc824fa81324ceb2a310104ea26d0ecd0be4e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=AE=8B=E6=96=87=E6=AD=A6?= <iyzsong@gmail.com>
Date: Fri, 16 Sep 2016 11:13:29 +0800
Subject: [PATCH 3/3] Update documentation for the usage of libltdl.
* doc/guile-dbi.texi: Adjust to the usage of libltdl.
---
guile-dbi/doc/guile-dbi.texi | 17 ++++++++++-------
1 file changed, 10 insertions(+), 7 deletions(-)
diff --git a/guile-dbi/doc/guile-dbi.texi b/guile-dbi/doc/guile-dbi.texi
index 4b0015f..02821c0 100644
--- a/guile-dbi/doc/guile-dbi.texi
+++ b/guile-dbi/doc/guile-dbi.texi
@@ -312,7 +312,7 @@ typedef struct g_db_handle
SCM constr;
SCM status; /* pair: car = error numeric code, cdr = status message */
SCM closed; /* boolean, TRUE if closed otherwise FALSE */
- void* handle;
+ lt_dlhandle handle;
void* db_info;
int in_free; /* boolean, used to avoid alloc during garbage collection */
@} gdbi_db_handle_t;
@@ -327,7 +327,7 @@ backend to the dbi interface library. Its car is returns a status code number,
cdr is a status return message.
@item @code{closed} boolean, @code{#t} if the connection is closed, and
@code{#f} otherwise.
-@item @code{handle} is a void pointer used to point to dynamically
+@item @code{handle} is a lt_dlhandle used to point to dynamically
loaded back-end library, filled by dbi-open @code{__gdbi_dbd_wrap}.
Set to ``NULL'' at connection close.
@item @code{db_info} is a void pointer used by the backends as a data
@@ -364,18 +364,21 @@ Used to expose guile-dbi symbols so, scheme can call them.
@node How plugins are loaded, How to write plugins, Internal functions, Internals and Database Drivers
@section How plugins are loaded
-Everything starts at @code{s_make_db_handle}. This function uses dlopen
-to load a shared library named ``libguile-dbd-bcknd.so''. bcknd is the
-first param of dbi-open.
+Everything starts at @code{s_make_db_handle}. This function uses
+libltdl to load a shared library named ``libguile-dbd-bcknd'' with the
+extension of ``.la'', ``.so'', etc. It's searched in the value of
+environment variable @code{GUILE_DBD_PATH} first, then libltdl's
+search patch and system library search path. bcknd is the first param
+of dbi-open.
@*
If the shared library is successfully loaded, the dbh's field ``handle''
-is filled with the pointer returned by ``dlopen'' and dbh->status is
+is filled with the pointer returned by ``lt_dlopen'' and dbh->status is
set. Otherwise the status is set to an error code in the car location,
while cdr is filled with an error message returned by @code{strerror}.
@*
-Once ``dlopen'' is ok, @code{__gdbi_dbd_wrap} is used to call the backend
+Once ``lt_dlopen'' is ok, @code{__gdbi_dbd_wrap} is used to call the backend
plugin connect function passing it the connection string. If this
step also succeeds, then the db should be connected.
@sp 1
--
2.10.0
[-- Attachment #5: Type: text/plain, Size: 27 bytes --]
Hope they are obvious :-)
^ permalink raw reply related [flat|nested] 5+ messages in thread