Hi again,
Attached is an initial patch (-p1) against your 2009-06-11 snapshot that
libtoolizes the build, among other things (I'll explain each piece):
autogen.sh: added libtoolize --ltdl (run me first!)
configure.ac:
AC_CANONICAL_HOST check for characteristics of platform,
needed by libtool macros.
AC_LIBLTDL_CONVENIENCE build against distributed libltdl,
which is bundled with gnucap after libtoolize.
This is common practice, as it doesn't require the
user to have libltdl pre-installed.
AC_DISABLE_STATIC (optional) just build for shared libraries
only to cut compilation time in half.
AC_CONFIG_SUBDIRS -- libltdl has its own config
LTDL_SHLIBPATH_VAR -- often DYLD_LIBRARY_PATH, but may vary
on different platforms.
removed -rdynamic, as it is not portable, and is replaced by
src/Makefile.am's -export-dynamic flag.
modelgen/Makefile.am:
AM_CPPFLAGS is more modern that INCLUDES
src/Makefile.am:
libgnucap.la: the core of gnucap, for now, this includes
everything but main.cc and the model files.
gnucapbasemodels.la: the base plug-in that contains
all of the models distributed with gnucap.
replaced pattern rules with real suffix rules for
Makefile portability, retained dependencies.
gnucap: reduced to main.cc, linking against own libgnucap
shared lib by default.
src/c_attach.cc:
added 'dlopen' command/class, similar to 'attach'.
calls lt_dlopenext() instead of dlopen().
src/main.cc:
calls to ltdl_init(), ltdl_exit()
I don't know if this is how you wanted the gnucap core library organized,
factoring out main.cc was just a guess.
I validated that the package as a whole still works by running 'make
distcheck'.
With this build, even the base models are not loaded on startup by gnucap!
On startup, one can load the base models:
from $(builddir)/src/:
$ ./gnucap
gnucap> dlopen gnucapbasemodels
gnucap> ...
gnucap> attach gnucapbasemodels.so
also works, but depends on the local system's plug-in extension.
(Does everything still work as expected for you after loading
gnucapbasemodels?)
*After* installation however, the env. var. DYLD_LIBRARY_PATH is used to
search for plug-ins by lt/dlopen(). Alternatively, we could have
libgnucap automatically prepend the $(pkglibdir) (where plugins are
installed) to the ltdl search path (call ld_dladdsearchdir), so the user
need not modify the environment, as long as plug-ins are installed to
$(pkglibdir).
What I haven't done yet:
I haven't built any of the other separately distributed models yet, I have
another proposal for them after we review this patch/ideas.
Other notes: do you plan to turn your examples dir into a test-suite (mke
check)? It seems users can already run them.
Documentation: If you have the sources for the html documentation I've
found online, were you planning on distributing them? perhaps as texinfo?
Texinfo is great for producing html/pdf/info docs from the same source.
automake has support for handling texinfo sources. You can also
distribute pre-built documentation so the user need not build it.
Fang
This rule applies to the program source too. The core has no
listing of what plugins might be used.
The only way I can think of to let the user specify what plugins
to static link is to let the user explicitly list them,
somewhere, or to include a file containing such a list.
Why not make every plug-in loadable via the following:
* command-line invocation when executable is run (e.g. -l featureXYZ)
* in-program command-line loading (e.g. "% load featureXYZ")
* configuration text file, editable by the user, like a .gnucaprc
This way you don't need to worry about adding configure-time options (decide
later!). The build system can just build all plugins with the base package
(unless explicitly disabled, or missing prereq is detected).
This gives the most flexibility to the user without having to make decisions
up-front. This is how many extension languages work (perl, python,
guile/scheme, tcl).
When a new plug-in comes along and is installed, the user just amends her
configuration file to load the new module.
This method is orthogonal to choice of build system, but using libtool to
manage building and installing of plug-ins is still what I'd recommend for
best portability (and ease of maintainence).
David Fang
http://www.csl.cornell.edu/~fang/
http://www.achronix.com/
diff -u -r gnucap-2009-06-11/Makefile.am gnucap-2009-06-11-patched/Makefile.am
--- gnucap-2009-06-11/Makefile.am 2008-06-01 07:58:12.000000000 -0700
+++ gnucap-2009-06-11-patched/Makefile.am 2009-06-20 17:51:23.000000000
-0700
@@ -2,7 +2,7 @@
##
## Top level automake file for gnucap
-SUBDIRS= doc examples modelgen src
+SUBDIRS = libltdl modelgen src doc examples
-EXTRA_DIST= autogen.sh Makefile.template configure.old
+EXTRA_DIST = autogen.sh Makefile.template configure.old
diff -u -r gnucap-2009-06-11/autogen.sh gnucap-2009-06-11-patched/autogen.sh
--- gnucap-2009-06-11/autogen.sh 2007-02-27 09:39:37.000000000 -0800
+++ gnucap-2009-06-11-patched/autogen.sh 2009-06-20 14:41:09.000000000
-0700
@@ -21,6 +21,9 @@
echo "Running autoconf..."
autoconf || exit 1
+echo "Running libtoolize..."
+libtoolize --ltdl || exit 1
+
echo "not Running configure..."
##./configure $@ || exit 1
diff -u -r gnucap-2009-06-11/configure.ac gnucap-2009-06-11-patched/configure.ac
--- gnucap-2009-06-11/configure.ac 2009-06-10 21:30:52.000000000 -0700
+++ gnucap-2009-06-11-patched/configure.ac 2009-06-20 18:48:23.000000000
-0700
@@ -28,9 +28,26 @@
AM_INIT_AUTOMAKE(gnucap, 2009-06-11)
AM_CONFIG_HEADER([config.h])
+AC_CANONICAL_HOST
AM_MAINTAINER_MODE
+# libtool setup
+AC_LIBLTDL_CONVENIENCE
+AC_SUBST(LTDLINCL)
+AC_SUBST(LIBLTDL)
+AC_LIB_LTDL
+AC_LIBTOOL_DLOPEN
+AC_DISABLE_STATIC
+AC_PROG_LIBTOOL
+AC_CONFIG_SUBDIRS(libltdl)
+dnl need these variables to augment test environment
+LTDL_SHLIBPATH_VAR=$libltdl_cv_shlibpath_var
+AC_SUBST(LTDL_SHLIBPATH_VAR)
+LTDL_OBJDIR=$libltdl_cv_objdir
+AC_SUBST(LTDL_OBJDIR)
+
+
AC_MSG_CHECKING([if debug code should be compiled in])
AC_ARG_ENABLE([debug],
[ --enable-debug Enable building of debug code. [[default:
disabled]]],
@@ -121,7 +138,8 @@
fi
# exports symbols to plugins
-LDFLAGS="$LDFLAGS -rdynamic"
+# LDFLAGS="$LDFLAGS -rdynamic"
+# use libtool flag -export-dynamic
#AC_OUTPUT([
# Makefile
diff -u -r gnucap-2009-06-11/modelgen/Makefile.am
gnucap-2009-06-11-patched/modelgen/Makefile.am
--- gnucap-2009-06-11/modelgen/Makefile.am 2009-06-10 21:19:47.000000000
-0700
+++ gnucap-2009-06-11-patched/modelgen/Makefile.am 2009-06-20
15:06:32.000000000 -0700
@@ -41,5 +41,5 @@
configure.old Makefile.template
-INCLUDES= -I$(top_srcdir)/src
+AM_CPPFLAGS = -I$(top_srcdir)/src
diff -u -r gnucap-2009-06-11/src/Makefile.am
gnucap-2009-06-11-patched/src/Makefile.am
--- gnucap-2009-06-11/src/Makefile.am 2009-06-10 21:20:12.000000000 -0700
+++ gnucap-2009-06-11-patched/src/Makefile.am 2009-06-20 17:49:57.000000000
-0700
@@ -24,6 +24,7 @@
## 02110-1301, USA.
bin_PROGRAMS= gnucap
+pkglib_LTLIBRARIES = libgnucap.la gnucapbasemodels.la
#------------------------------------------------------------------------
# These source files can be omitted, and supplied as plugins.
@@ -91,7 +92,8 @@
e_elemnt.cc e_ccsrc.cc e_storag.cc e_cardlist.cc \
bm_model.cc bm_value.cc bm_cond.cc bm.cc \
c__cmd.cc c_attach.cc c_file.cc c_genrat.cc \
-findbr.cc plot.cc main.cc globals.cc
+findbr.cc plot.cc globals.cc
+# main.cc
#------------------------------------------------------------------------
RAW_HDRS = \
md.h ap.h mode.h constant.h declare.h patchlev.h \
@@ -111,40 +113,54 @@
c_comand.h globals.h
#------------------------------------------------------------------------
## The modelgen generated files
-MODELSRCS= ${MODELS:.model=.cc} ${MODELS:.model=.h}
+MODELSRCS= ${MODELS:.model=.cc}
+MODELHDRS= ${MODELS:.model=.h}
MODELOBJS= ${MODELS:.model=.${OBJEXT}}
+MODELLTOBJS= ${MODELS:.model=.lo}
-nodist_gnucap_SOURCES= ${SRCS1} ${MODELSRCS} ${SRCS2}
+nodist_gnucapbasemodels_la_SOURCES = ${MODELSRCS} ${MODELHDRS}
+gnucapbasemodels_la_LDFLAGS = -module
SRCS1=
SRCS2= ${RAW_SRCS} ${RAW_HDRS}
+libgnucap_la_SOURCES= ${SRCS1} ${SRCS2}
+libgnucap_la_LIBADD= ${LIBLTDL}
+
+gnucap_SOURCES= main.cc
+gnucap_LDADD = libgnucap.la
+# if symbols from executable are needed for plug-in modules
+gnucap_LDFLAGS = -export-dynamic
+
# make all of the model object files depend on all of the model sources
# this is a bit overkill, but for example the bjt model makes use of the
# diode model and we want to be sure and capture that dependency
-${MODELOBJS}: ${MODELSRCS}
+${MODELOBJS} ${MODELLTOBJS}: ${MODELSRCS} ${MODELHDRS}
## Include the .model files in the distfile as well as the rest of the
## non-generated sources
-EXTRA_DIST= ${MODELS} ${SRCS1} ${SRCS2} \
+EXTRA_DIST= ${MODELS} \
configure.old Make1 test_readline.cc spice-wrapper.cc \
Make3 Makefile.template \
Make2.g++ Make2.Debug Make2.mingw32 \
Makefile.am
### Clean out the modelgen generated files
-CLEANFILES= ${MODELSRCS}
+CLEANFILES= ${MODELSRCS} ${MODELHDRS}
## Suffix rules for modelgen.
##
-SUFFIXES= .model
+SUFFIXES= .model .cc .h
MODELGEN= @MODELGEN@
+MODELGENEXE = ${MODELGEN}${EXEEXT}
+
+.model.cc:
+ ${MODELGENEXE} -cc $<
-%.cc : %.model %.h ${MODELGEN}${EXEEXT}
- ${MODELGEN} -cc $<
+.model.h:
+ ${MODELGENEXE} -h $<
-%.h : %.model ${MODELGEN}${EXEEXT}
- ${MODELGEN} -h $<
+${MODELSRCS} ${MODELHDRS}: ${MODELGENEXE}
diff -u -r gnucap-2009-06-11/src/c_attach.cc
gnucap-2009-06-11-patched/src/c_attach.cc
--- gnucap-2009-06-11/src/c_attach.cc 2009-06-10 21:20:11.000000000 -0700
+++ gnucap-2009-06-11-patched/src/c_attach.cc 2009-06-20 19:34:20.000000000
-0700
@@ -23,6 +23,7 @@
//testing=informal
#include "c_comand.h"
#include "globals.h"
+#include "../libltdl/ltdl.h"
/*--------------------------------------------------------------------------*/
namespace {
/*--------------------------------------------------------------------------*/
@@ -77,6 +78,24 @@
} p1;
DISPATCHER<CMD>::INSTALL d1(&command_dispatcher, "attach|load", &p1);
/*--------------------------------------------------------------------------*/
+class CMD_DLOPEN : public CMD {
+public:
+ void do_it(CS& cmd, CARD_LIST*)
+ {itested();
+ if (cmd.more()) {itested();
+ // TODO: use something like a reference-counted pointer
+ // so that libraries are automatically dlclose()'d upon destruction
+ lt_dlhandle_struct* const mh = lt_dlopenext(cmd.tail().c_str());
+ if (!mh) {
+ throw Exception("Failed to load module\n"
+ "You may need to adjust your dynamic library serach
paths.");
+ }
+ }
+ // else do nothing
+ }
+} p4;
+DISPATCHER<CMD>::INSTALL d4(&command_dispatcher, "dlopen", &p4);
+/*--------------------------------------------------------------------------*/
class CMD_DETACH : public CMD {
public:
void do_it(CS& cmd, CARD_LIST*)
diff -u -r gnucap-2009-06-11/src/main.cc gnucap-2009-06-11-patched/src/main.cc
--- gnucap-2009-06-11/src/main.cc 2009-06-10 21:20:11.000000000 -0700
+++ gnucap-2009-06-11-patched/src/main.cc 2009-06-20 17:47:34.000000000
-0700
@@ -28,6 +28,7 @@
#include "patchlev.h"
#include "c_comand.h"
#include "declare.h" /* plclose */
+#include "../libltdl/ltdl.h"
/*--------------------------------------------------------------------------*/
struct JMP_BUF{
sigjmp_buf p;
@@ -176,8 +177,31 @@
}
}
/*--------------------------------------------------------------------------*/
+/**
+ Class whose sole responsibility is to balance dlinit with dlexit,
+ using constructor/destructor duality, thereby guaranteeing
+ exception safety and non-leaking.
+ Provided by Fang.
+ */
+class ltdl_token {
+public:
+ ltdl_token() { lt_dlinit(); }
+ ~ltdl_token() { lt_dlexit(); }
+
+private:
+ ltdl_token(const ltdl_token&);
+
+ ltdl_token&
+ operator = (const ltdl_token&);
+
+ // also stack-allocate only...
+} /* __attribute__((unused)) */ ;
+
+
+/*--------------------------------------------------------------------------*/
int main(int argc, const char *argv[])
{
+ const ltdl_token __lt__;
{
SET_RUN_MODE xx(rBATCH);
sign_on();
_______________________________________________
Gnucap-devel mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/gnucap-devel