Re: Autotools build system
David Fang <[email protected]>
| Newsgroups | gmane.comp.gnu.gnucap.devel |
|---|---|
| Message-ID | <[email protected]> |
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/ _______________________________________________ Gnucap-devel mailing list [email protected] http://lists.gnu.org/mailman/listinfo/gnucap-devel
gnucap-2009-06-11.patch
(text/plain, 7.8 KB)
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();