Subject: [PATCH] Add USE_SHARED_LIBGIT flag to build and use libgit.so rather than libgit.a

From: Josh Triplett <[email-masked]>
Date: Sun, 01 Jul 2007 01:28:02 -0700

Git builds a static libgit.a, and many commands which link to libgit.a,
resulting in many duplicate copies of the code in libgit.a.  Add a
USE_SHARED_LIBGIT flag to the Makefile (off by default), which builds and uses
a shared library libgit.so instead.

The existing objects in libgit.a reference the symbols git_version_string and
git_usage_string, defined in git.c, but libgit does not include git.o, making
the library not self-contained, and leading to linking errors when trying to
use a shared library.  Move those two symbols to help.c, where the references
from libgit occur.

This change does not install header files, versioned libraries, or anything
else that would support actually using libgit.so from anything other than the
installed git binaries.  The built libgit.so exists solely for the benefit of
the installed git binaries that link to it.

Motivated by trying to install Git on a machine for which this makes the
difference between remaining under quota and not.

Signed-off-by: Josh Triplett <[email-masked]>
---
 Makefile |   31 ++++++++++++++++++++++++++-----
 git.c    |    5 -----
 help.c   |    5 +++++
 3 files changed, 31 insertions(+), 10 deletions(-)

diff --git a/Makefile b/Makefile
index a98e27a..db35b3b 100644
--- a/Makefile
+++ b/Makefile
@@ -124,6 +124,8 @@ all::
 # If not set it defaults to the bare 'wish'. If it is set to the empty
 # string then NO_TCLTK will be forced (this is used by configure script).
 #
+# Define USE_SHARED_LIBGIT to create and use a shared library libgit.so rather
+# than a static library libgit.a.
 
 GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
 	@$(SHELL_PATH) ./GIT-VERSION-GEN
@@ -146,6 +148,7 @@ STRIP ?= strip
 prefix = $(HOME)
 bindir = $(prefix)/bin
 gitexecdir = $(bindir)
+libdir = $(prefix)/lib
 sharedir = $(prefix)/share
 template_dir = $(sharedir)/git-core/templates
 ifeq ($(prefix),/usr)
@@ -290,7 +293,13 @@ endif
 
 export PERL_PATH
 
+ifdef USE_SHARED_LIBGIT
+LIB_FILE=libgit.so
+LIBGIT=-L. -lgit
+else
 LIB_FILE=libgit.a
+LIBGIT=$(LIB_FILE)
+endif
 XDIFF_LIB=xdiff/lib.a
 
 LIB_H = \
@@ -704,6 +713,7 @@ ETC_GITCONFIG_SQ = $(subst ','\'',$(ETC_GITCONFIG))
 DESTDIR_SQ = $(subst ','\'',$(DESTDIR))
 bindir_SQ = $(subst ','\'',$(bindir))
 gitexecdir_SQ = $(subst ','\'',$(gitexecdir))
+libdir_SQ = $(subst ','\'',$(libdir))
 template_dir_SQ = $(subst ','\'',$(template_dir))
 prefix_SQ = $(subst ','\'',$(prefix))
 
@@ -712,7 +722,7 @@ PERL_PATH_SQ = $(subst ','\'',$(PERL_PATH))
 PYTHON_PATH_SQ = $(subst ','\'',$(PYTHON_PATH))
 TCLTK_PATH_SQ = $(subst ','\'',$(TCLTK_PATH))
 
-LIBS = $(GITLIBS) $(EXTLIBS)
+LIBS = $(LIBGIT) $(XDIFF_LIB) $(EXTLIBS)
 
 BASIC_CFLAGS += -DSHA1_HEADER='$(SHA1_HEADER_SQ)' \
 	-DETC_GITCONFIG='"$(ETC_GITCONFIG_SQ)"' $(COMPAT_CFLAGS)
@@ -721,6 +731,10 @@ LIB_OBJS += $(COMPAT_OBJS)
 ALL_CFLAGS += $(BASIC_CFLAGS)
 ALL_LDFLAGS += $(BASIC_LDFLAGS)
 
+ifdef USE_SHARED_LIBGIT
+ALL_CFLAGS += -fpic
+endif
+
 export TAR INSTALL DESTDIR SHELL_PATH

@@ -747,16 +761,15 @@ gitk-wish: gitk GIT-GUI-VARS
 	chmod +x $@+ && \
 	mv -f $@+ $@
 
-git.o: git.c common-cmds.h GIT-CFLAGS
-	$(QUIET_CC)$(CC) -DGIT_VERSION='"$(GIT_VERSION)"' \
-		$(ALL_CFLAGS) -c $(filter %.c,$^)
+git.o: common-cmds.h
 
 git$X: git.o $(BUILTIN_OBJS) $(GITLIBS)
 	$(QUIET_LINK)$(CC) -DGIT_VERSION='"$(GIT_VERSION)"' \
 		$(ALL_CFLAGS) -o $@ $(filter %.c,$^) git.o \
 		$(BUILTIN_OBJS) $(ALL_LDFLAGS) $(LIBS)
 
-help.o: common-cmds.h
+help.o: help.c common-cmds.h GIT-CFLAGS
+	$(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DGIT_VERSION='"$(GIT_VERSION)"' $<
 
 git-merge-subtree$X: git-merge-recursive$X
 	$(QUIET_BUILT_IN)rm -f $@ && ln git-merge-recursive$X $@
@@ -908,7 +921,11 @@ $(patsubst git-%$X,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h)
 $(DIFF_OBJS): diffcore.h
 
 $(LIB_FILE): $(LIB_OBJS)
+ifdef USE_SHARED_LIBGIT
+	$(QUIET_LINK)$(CC) -shared -o $@ $(LIB_OBJS)
+else
 	$(QUIET_AR)rm -f $@ && $(AR) rcs $@ $(LIB_OBJS)
+endif
 
 XDIFF_OBJS=xdiff/xdiffi.o xdiff/xprepare.o xdiff/xutils.o xdiff/xemit.o \
 	xdiff/xmerge.o
@@ -996,6 +1013,10 @@ install: all
 	$(INSTALL) -d -m755 '$(DESTDIR_SQ)$(gitexecdir_SQ)'
 	$(INSTALL) $(ALL_PROGRAMS) '$(DESTDIR_SQ)$(gitexecdir_SQ)'
 	$(INSTALL) git$X '$(DESTDIR_SQ)$(bindir_SQ)'
+ifdef USE_SHARED_LIBGIT
+	$(INSTALL) -d -m755 $(DESTDIR_SQ)$(libdir_SQ)
+	$(INSTALL) $(LIB_FILE) $(DESTDIR_SQ)$(libdir_SQ)
+endif
 	$(MAKE) -C templates DESTDIR='$(DESTDIR_SQ)' install
 	$(MAKE) -C perl prefix='$(prefix_SQ)' install
 ifndef NO_TCLTK
diff --git a/git.c b/git.c
index 29b55a1..1e24903 100644
--- a/git.c
+++ b/git.c
@@ -3,9 +3,6 @@
 #include "cache.h"
 #include "quote.h"
 
-const char git_usage_string[] =
-	"git [--version] [--exec-path[=GIT_EXEC_PATH]] [-p|--paginate] [--bare] [--git-dir=GIT_DIR] [--help] COMMAND [ARGS]";
-
 static void prepend_to_path(const char *dir, int len)
 {
 	const char *old_path = getenv("PATH");
@@ -206,8 +203,6 @@ static int handle_alias(int *argcp, const char ***argv)
 	return ret;
 }
 
-const char git_version_string[] = GIT_VERSION;
-
 #define RUN_SETUP	(1<<0)
 #define USE_PAGER	(1<<1)
 /*
diff --git a/help.c b/help.c
index 1cd33ec..3f3ceeb 100644
--- a/help.c
+++ b/help.c
@@ -9,6 +9,11 @@
 #include "common-cmds.h"
 #include <sys/ioctl.h>
 
+const char git_usage_string[] =
+	"git [--version] [--exec-path[=GIT_EXEC_PATH]] [-p|--paginate] [--bare] [--git-dir=GIT_DIR] [--help] COMMAND [ARGS]";
+
+const char git_version_string[] = GIT_VERSION;
+
 /* most GUI terminals set COLUMNS (although some don't export it) */
 static int term_columns(void)
 {
-- 
1.5.2.2