NOTES ON BUILDING LIBG++ AS A SUNOS4 SHARED LIBRARY

A shared library version of libg++-2.6.1 can be built using gcc-2.6.0 on a 
SPARC10 running OS4.1.3. In order to get SUN shared libraries to work 
properly with g++ it was necessary to patch collect2 [ld].  A hack of an 
earlier version of collect2 done by Eric Schenk [schenk@cs.toronto.edu] was 
massaged to work with gcc-2.6.0.  A context diff is included below.

To build a shared version of libg++ on a SPARC running OS4.1.3 
do the following:

(0) patch collect2.c in gcc-2.6.1 and rebuild
(1) patch libg++-2.6.1
(2) start with a *clean* libg++-2.6.1 tree [make distclean] 
(3) configure
(4) edit the top-level Makefile:

	CC = gcc
	CFLAGS = -g -O2 -fpic
	CXXFLAGS = -g -O2 -fpic -fno-implicit-templates

(5) run make
(6) build the shared lib from the PIC code
    (a) cd libg++-2.6.1/libg++
    (b) mkdir shared
    (c) cd shared
    (d) ar xv ../libg++.a
    (e) mkdir unshared
    (f) mv CursesW.o  ./unshared
    (g) ld -o ../libg++.so.2.61 *.o -assert pure-text
    (h) cd ./unshared
    (i) ar rcv ../../libg++.sa.2.61 *.o
    (j) ranlib ../../libg++.sa.2.61


Discussion:
----------

The SUN link editor has an idiosyncracy [bug ???] which requires anything
that is declared in a shared library to be defined even if it isn't used.
CursesW.o declares functions that are defined in libcurses and libtermcap. 
If CursesW.o had been incorporated into the ".so" piece, these two 
libraries would  have to be added to the link statement even when the 
CursesWindow class is not being used.  This situation was alleviated by 
placing CursesW.0 into the ".sa" piece.

In addition, libg++.so.2.61 contains a number of classes which use the math
library.  Consequently, the math library must to added to the link command
even if these classes are not used.  There are far too many of these classes
that declare math functions so it is just easier to add "-lm" to the link
command.  One might consider splitting libg++ into two libraries: one that
contains the contributions from libio and libiberty and another that contains
Doug Lea's classes.  I've done some experimenting in this direction and have
seen that such an approach is certainly viable.


-----------------------collect2.c patch---------------------------------------
*** collect2.c.orig	Mon Jul 11 15:08:16 1994
--- collect2.c	Sun Jul 31 09:38:09 1994
***************
*** 24,29 ****
--- 24,34 ----
  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  
  
+ #ifdef sparc
+ #define SUNOS_SHARED_LIBS /* This should really be defined in a config file */
+ #endif
+ 
+ 
  /* Build tables of static constructors and destructors and run ld. */
  
  #include <sys/types.h>
***************
*** 223,231 ****
--- 228,243 ----
  static struct head constructors;	/* list of constructors found */
  static struct head destructors;		/* list of destructors found */
  
+ #ifdef SUNOS_SHARED_LIBS
+ static struct head shared_libs;     /* list of shared libraries to scan */
+ #endif
+ 
  extern char *getenv ();
  extern char *mktemp ();
  extern FILE *fdopen ();
+ #ifdef SUNOS_SHARED_LIBS
+ static void  exec_ldd ();
+ #endif
  
  /* Structure to hold all the directories in which to search for files to
     execute.  */
***************
*** 1181,1186 ****
--- 1193,1211 ----
  
    scan_prog_file (output_file, PASS_FIRST);
  
+ #ifdef SUNOS_SHARED_LIBS
+   /* Call ldd to determine dynamic depenencies, */
+   /* and scan all .so files as well. */
+   exec_ldd(output_file);
+   {
+     struct id *lib = shared_libs.first;
+     while (lib) {
+       scan_prog_file (lib->name, PASS_FIRST);
+       lib = lib->next;
+     }
+   }
+ #endif
+ 
    if (debug)
      {
        fprintf (stderr, "%d constructor(s) found\n", constructors.number);
***************
*** 1328,1333 ****
--- 1353,1470 ----
  
    do_wait (prog);
  }
+ 
+ #ifdef SUNOS_SHARED_LIBS
+ static void
+ exec_ldd (outfile)
+      char *outfile;
+ {
+   void (*int_handler) ();
+   void (*quit_handler) ();
+ 
+   char *ldd_argv[3];
+ 
+   int pid;
+   int argc = 0;
+   int pipe_fd[2];
+   char *p, buf[1024];
+   FILE *inf;
+ 
+   ldd_argv[argc++] = "ldd";
+   ldd_argv[argc++] = outfile;
+   ldd_argv[argc++] = (char *)0;
+ 
+   if (pipe (pipe_fd) < 0)
+     fatal_perror ("pipe");
+ 
+   inf = fdopen (pipe_fd[0], "r");
+   if (inf == (FILE *)0)
+     fatal_perror ("fdopen");
+ 
+   /* Trace if needed.  */
+   if (vflag || debug)
+     {
+       char **p_argv;
+       char *str;
+ 
+       fprintf (stderr, "%s", "/bin/ldd");
+       for (p_argv = &ldd_argv[1]; (str = *p_argv) != (char *)0; p_argv++)
+       fprintf (stderr, " %s", str);
+ 
+       fprintf (stderr, "\n");
+     }
+ 
+   fflush (stdout);
+   fflush (stderr);
+ 
+   /* Spawn child ld on pipe */
+   pid = vfork ();
+   if (pid == -1)
+     fatal_perror ("vfork");
+ 
+   if (pid == 0)                       /* child context */
+     {
+       /* setup stdout */
+       if (dup2 (pipe_fd[1], 1) < 0)
+         fatal_perror ("Dup2 (%d, 1)", pipe_fd[1]);
+ 
+       if (close (pipe_fd[0]) < 0)
+         fatal_perror ("Close (%d)", pipe_fd[0]);
+ 
+       if (close (pipe_fd[1]) < 0)
+         fatal_perror ("Close (%d)", pipe_fd[1]);
+ 
+       execv ("/bin/ldd", ldd_argv);
+       fatal_perror ("Execute %s", "/bin/ldd");
+     }
+ 
+   /* Parent context from here on.  */
+   int_handler  = (void (*) ())signal (SIGINT,  SIG_IGN);
+   quit_handler = (void (*) ())signal (SIGQUIT, SIG_IGN);
+ 
+   if (close (pipe_fd[1]) < 0)
+     fatal_perror ("Close (%d)", pipe_fd[1]);
+ 
+   if (debug)
+     fprintf (stderr, "\nfind dependencies on shared libraries.\n");
+ 
+   /* Read each line of ldd output.  */
+   while (fgets (buf, sizeof buf, inf) != (char *)0)
+     {
+       int ch, ch2;
+       char *start;
+       char *end;
+ 
+       /* Skip lines that complain about static linking */
+       if (strstr(buf,"statically linked") != 0) continue;
+ 
+       /* Find end of library name and null-terminate it.  */
+       end = &buf[strlen(buf)-1];
+       if (*end == '\n') (*end--) = 0;
+ 
+       /* work backwards to find the start of the library name */
+       start = end;
+       while (!isspace(*start)) start--;
+       start++;
+ 
+       add_to_list (&shared_libs, start);
+ 
+       if (debug)
+         fprintf (stderr, "\t%s\n", buf);
+     }
+ 
+   if (debug)
+     fprintf (stderr, "\n");
+ 
+   if (fclose (inf) != 0)
+     fatal_perror ("fclose of pipe");
+ 
+   do_wait ("/bin/ldd");
+ 
+   signal (SIGINT,  int_handler);
+   signal (SIGQUIT, quit_handler);
+ }
+ #endif
  
  
  /* Unlink a file unless we are debugging.  */
-------------------------libg++-2.6.1 patches--------------------------------
*** ./libg++/src/DLList.h.dist	Thu Oct 20 11:25:30 1994
--- ./libg++/src/DLList.h	Thu Oct 20 14:24:13 1994
***************
*** 52,58 ****
      virtual void delete_node(BaseDLNode*node) = 0;
      virtual BaseDLNode* copy_node(const void* datum) = 0;
      virtual void copy_item(void *dst, void *src) = 0;
!     virtual ~BaseDLList() { }
  
      Pix                   prepend(const void*);
      Pix                   append(const void*);
--- 52,59 ----
      virtual void delete_node(BaseDLNode*node) = 0;
      virtual BaseDLNode* copy_node(const void* datum) = 0;
      virtual void copy_item(void *dst, void *src) = 0;
!     virtual ~BaseDLList();
! 
  
      Pix                   prepend(const void*);
      Pix                   append(const void*);
*** ./libg++/src/SLList.h.dist	Thu Oct 20 11:25:53 1994
--- ./libg++/src/SLList.h	Thu Oct 20 14:26:54 1994
***************
*** 49,55 ****
      virtual void delete_node(BaseSLNode*node) = 0;
      virtual BaseSLNode* copy_node(const void* datum) = 0;
      virtual void copy_item(void *dst, void *src) = 0;
!     virtual ~BaseSLList() { }
      BaseSLList() { last = 0; }
      void copy(const BaseSLList&);
      BaseSLList& operator = (const BaseSLList& a);
--- 49,55 ----
      virtual void delete_node(BaseSLNode*node) = 0;
      virtual BaseSLNode* copy_node(const void* datum) = 0;
      virtual void copy_item(void *dst, void *src) = 0;
!     virtual ~BaseSLList() ;
      BaseSLList() { last = 0; }
      void copy(const BaseSLList&);
      BaseSLList& operator = (const BaseSLList& a);
*** ./libg++/src/DLList.cc.dist	Thu Oct 20 14:24:27 1994
--- ./libg++/src/DLList.cc	Thu Oct 20 14:25:59 1994
***************
*** 25,30 ****
--- 25,32 ----
  #include <builtin.h>
  #include "DLList.h"
  
+ BaseDLList::~BaseDLList() {};
+ 
  void BaseDLList::error(const char* msg) const
  {
    (*lib_error_handler)("DLList", msg);
*** ./libg++/src/SLList.cc.dist	Thu Oct 20 14:26:28 1994
--- ./libg++/src/SLList.cc	Thu Oct 20 14:27:26 1994
***************
*** 25,30 ****
--- 25,32 ----
  #include <builtin.h>
  #include "SLList.h"
  
+ BaseSLList::~BaseSLList() {};
+ 
  void BaseSLList::error(const char* msg) const
  {
    (*lib_error_handler)("SLList", msg);
*** ./libio/procbuf.h.dist	Thu Oct 20 12:08:36 1994
--- ./libio/procbuf.h	Thu Oct 20 12:09:31 1994
***************
*** 30,36 ****
      /* Following fields must match those in struct _IO_proc_file */
      _IO_pid_t _pid;
    public:
!     procbuf() : filebuf() { }
      procbuf(const char *command, int mode);
      procbuf* open(const char *command, int mode);
      procbuf *close() { return (procbuf*)filebuf::close(); }
--- 30,36 ----
      /* Following fields must match those in struct _IO_proc_file */
      _IO_pid_t _pid;
    public:
!     procbuf();
      procbuf(const char *command, int mode);
      procbuf* open(const char *command, int mode);
      procbuf *close() { return (procbuf*)filebuf::close(); }
*** ./libio/procbuf.cc.dist	Thu Oct 20 12:09:05 1994
--- ./libio/procbuf.cc	Thu Oct 20 12:10:10 1994
***************
*** 28,33 ****
--- 28,35 ----
  #include "libioP.h"
  #include "procbuf.h"
  
+ procbuf::procbuf() : filebuf() {}
+ 
  procbuf::procbuf(const char *command, int mode) : filebuf()
  {
    _IO_proc_open(this, command, (mode & ios::in) ? "r" : "w");


-- 
Dr. Joseph E. Sacco            | Internet: jsacco@ssl.com
Sacco Scientific               | 
6 Buena Vista Street           | FAX:      (617)233-3611
Saugus, MA 01906-2606          | Voice:    (617)233-4212
