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();
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.