[PATCH] Makefile: re-use Git's Makefile where possible

Jamie Couture jamie.couture at gmail.com
Tue Mar 5 21:39:34 CET 2013


On Tue, Mar 05, 2013 at 08:12:54PM +0000, John Keeping wrote:
> Git does quite a lot of platform-specific detection in its Makefile,
> which can result in it defining preprocessor variables that are used in
> its header files.  If CGit does not define the same variables it can
> result in different sizes of some structures in different places in the
> same application.
> 
> For example, on Solaris Git uses it's "compat" regex library which has a
> different sized regex_t structure than that available in the platform
> regex.h.  This has a knock-on effect on the size of "struct rev_info"
> and leads to hard to diagnose runtime issues.
> 
> In order to avoid all of this, introduce a "cgit.mk" file that includes
> Git's Makefile and make all of the existing logic apply to CGit's
> objects as well.  This is slightly complicated because Git's Makefile
> must run in Git's directory, so all references to CGit files need to be
> prefixed with "../".
> 
> In addition, OBJECTS is a simply expanded variable in Git's Makefile so
> we cannot just add our objects to it.  Instead we must copy the two
> applicable rules into "cgit.mk".  This has the advantage that we can
> split CGit-specific CFLAGS from Git's CFLAGS and hence avoid rebuilding
> all of Git whenever a CGit-specific value changes.
> 
> Signed-off-by: John Keeping <john at keeping.me.uk>
> ---
> I tried compiling CGit on Solaris since that's always a good way of
> exposing cross-platform issues.  Trying to figure out why
> rev_info->graph suddenly because non-null took me longer than I'd like
> to admit (it follows the embedded regex_t structure in rev_info and was
> being stomped on because Git thought the regex_t structure was 8 bytes
> bigger than CGit).
> 
> This is the best way I can see to make sure that we avoid all potential
> issues with #defines having different values for CGit objects and Git
> objects, but perhaps someone else has a better idea?
> 
>  .gitignore |   1 +
>  Makefile   | 124 +++----------------------------------------------------------
>  cgit.mk    |  72 +++++++++++++++++++++++++++++++++++
>  3 files changed, 78 insertions(+), 119 deletions(-)
>  create mode 100644 cgit.mk
> 
> diff --git a/.gitignore b/.gitignore
> index 487728b..8011b39 100644
> --- a/.gitignore
> +++ b/.gitignore
> @@ -1,6 +1,7 @@
>  # Files I don't care to see in git-status/commit
>  cgit
>  cgit.conf
> +CGIT-CFLAGS
>  VERSION
>  cgitrc.5
>  cgitrc.5.fo
> diff --git a/Makefile b/Makefile
> index 1127961..8c00190 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -23,13 +23,6 @@ DOC_MAN5 = $(patsubst %.txt,%,$(MAN5_TXT))
>  DOC_HTML = $(patsubst %.txt,%.html,$(MAN_TXT))
>  DOC_PDF  = $(patsubst %.txt,%.pdf,$(MAN_TXT))
>  
> -# Define NO_STRCASESTR if you don't have strcasestr.
> -#
> -# Define NO_OPENSSL to disable linking with OpenSSL and use bundled SHA1
> -# implementation (slower).
> -#
> -# Define NEEDS_LIBICONV if linking with libc is not enough (eg. Darwin).
> -#
>  # Define NO_C99_FORMAT if your formatted IO functions (printf/scanf et.al.)
>  # do not support the 'size specifiers' introduced by C99, namely ll, hh,
>  # j, z, t. (representing long long int, char, intmax_t, size_t, ptrdiff_t).
> @@ -39,22 +32,12 @@ DOC_PDF  = $(patsubst %.txt,%.pdf,$(MAN_TXT))
>  #-include config.mak
>  
>  #
> -# Platform specific tweaks
> -#
> -
> -VERSION: force-version
> -	@./gen-version.sh "$(CGIT_VERSION)"
> --include VERSION
> -
> -uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')
> -uname_O := $(shell sh -c 'uname -o 2>/dev/null || echo not')
> -uname_R := $(shell sh -c 'uname -r 2>/dev/null || echo not')
> -
> -#
>  # Let the user override the above settings.
>  #
>  -include cgit.conf
>  
> +export CGIT_SCRIPT_NAME CGIT_SCRIPT_PATH CGIT_DATA_PATH CGIT_CONFIG CACHE_ROOT
> +
>  #
>  # Define a way to invoke make in subdirs quietly, shamelessly ripped
>  # from git.git
> @@ -69,8 +52,6 @@ NO_SUBDIR = :
>  endif
>  
>  ifndef V
> -	QUIET_CC       = @echo '   ' CC $@;
> -	QUIET_LINK     = @echo '   ' LINK $@;
>  	QUIET_SUBDIR0  = + at subdir=
>  	QUIET_SUBDIR1  = ;$(NO_SUBDIR) echo '   ' SUBDIR $$subdir; \
>  			 $(MAKE) $(PRINT_DIR) -C $$subdir
> @@ -78,107 +59,12 @@ ifndef V
>  	export V
>  endif
>  
> -LDFLAGS ?=
> -CFLAGS ?= -g -Wall
> -CFLAGS += -Igit
> -CFLAGS += -DSHA1_HEADER='$(SHA1_HEADER)'
> -CFLAGS += -DCGIT_VERSION='"$(CGIT_VERSION)"'
> -CFLAGS += -DCGIT_CONFIG='"$(CGIT_CONFIG)"'
> -CFLAGS += -DCGIT_SCRIPT_NAME='"$(CGIT_SCRIPT_NAME)"'
> -CFLAGS += -DCGIT_CACHE_ROOT='"$(CACHE_ROOT)"'
> -
> -ifeq ($(uname_O),Cygwin)
> -	NO_STRCASESTR = YesPlease
> -	NEEDS_LIBICONV = YesPlease
> -endif
> -
> -ifeq ($(uname_S),$(filter $(uname_S),FreeBSD OpenBSD))
> -	# Apparantly libiconv is installed in /usr/local on BSD
> -	LDFLAGS += -L/usr/local/lib
> -	CFLAGS += -I/usr/local/include
> -	NEEDS_LIBICONV = yes
> -endif
> -
> -GIT_OPTIONS = prefix=/usr NO_GETTEXT=1
> -OBJECTS =
> -
> -ifdef NO_ICONV
> -	CFLAGS += -DNO_ICONV
> -endif
> -ifdef NO_STRCASESTR
> -	CFLAGS += -DNO_STRCASESTR
> -endif
> -ifdef NO_C99_FORMAT
> -	CFLAGS += -DNO_C99_FORMAT
> -endif
> -ifdef NO_OPENSSL
> -	CFLAGS += -DNO_OPENSSL
> -	GIT_OPTIONS += NO_OPENSSL=1
> -else
> -	LDLIBS += -lcrypto
> -endif
> -
> -ifdef NEEDS_LIBICONV
> -	LDLIBS += -liconv
> -endif
> -
> -LDLIBS += git/libgit.a git/xdiff/lib.a -lz -lpthread
> -
> -OBJECTS += cgit.o
> -OBJECTS += cache.o
> -OBJECTS += cmd.o
> -OBJECTS += configfile.o
> -OBJECTS += html.o
> -OBJECTS += parsing.o
> -OBJECTS += scan-tree.o
> -OBJECTS += shared.o
> -OBJECTS += ui-atom.o
> -OBJECTS += ui-blob.o
> -OBJECTS += ui-clone.o
> -OBJECTS += ui-commit.o
> -OBJECTS += ui-diff.o
> -OBJECTS += ui-log.o
> -OBJECTS += ui-patch.o
> -OBJECTS += ui-plain.o
> -OBJECTS += ui-refs.o
> -OBJECTS += ui-repolist.o
> -OBJECTS += ui-shared.o
> -OBJECTS += ui-snapshot.o
> -OBJECTS += ui-ssdiff.o
> -OBJECTS += ui-stats.o
> -OBJECTS += ui-summary.o
> -OBJECTS += ui-tag.o
> -OBJECTS += ui-tree.o
> -OBJECTS += vector.o
> -
> -dep_files := $(foreach f,$(OBJECTS),$(dir $f).deps/$(notdir $f).d)
> -dep_dirs := $(addsuffix .deps,$(sort $(dir $OBJECTS)))
> -
> -$(dep_dirs):
> -	@mkdir -p $@
> -
> -missing_dep_dirs := $(filter-out $(wildcard $(dep_dirs)),$(dep_dirs))
> -dep_file = $(dir $@).deps/$(notdir $@).d
> -dep_args = -MF $(dep_file) -MMD -MP
> -
>  .SUFFIXES:
>  
> -$(OBJECTS): %.o: %.c $(missing_dep_dirs)
> -	$(QUIET_CC)$(CC) -o $*.o -c $(dep_args) $(CFLAGS) $<
> -
> -dep_files_present := $(wildcard $(dep_files))
> -ifneq ($(dep_files_present),)
> -include $(dep_files_present)
> -endif
> -
>  all:: cgit
>  
> -cgit: VERSION $(OBJECTS) libgit
> -	$(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) $(LDLIBS)
> -
> -libgit:
> -	$(QUIET_SUBDIR0)git $(QUIET_SUBDIR1) NO_CURL=1 $(GIT_OPTIONS) libgit.a
> -	$(QUIET_SUBDIR0)git $(QUIET_SUBDIR1) NO_CURL=1 $(GIT_OPTIONS) xdiff/lib.a
> +cgit:
> +	$(QUIET_SUBDIR0)git $(QUIET_SUBDIR1) -f ../cgit.mk ../cgit NO_CURL=1
>  
>  test: all
>  	$(QUIET_SUBDIR0)tests $(QUIET_SUBDIR1) all
> @@ -259,7 +145,7 @@ get-git:
>  tags:
>  	$(QUIET_TAGS)find . -name '*.[ch]' | xargs ctags
>  
> -.PHONY: all cgit get-git libgit force-version
> +.PHONY: all cgit get-git
>  .PHONY: clean clean-doc cleanall
>  .PHONY: doc doc-html doc-man doc-pdf
>  .PHONY: install install-doc install-html install-man install-pdf
> diff --git a/cgit.mk b/cgit.mk
> new file mode 100644
> index 0000000..9226d94
> --- /dev/null
> +++ b/cgit.mk
> @@ -0,0 +1,72 @@
> +# This Makefile is run in the "git" directory in order to re-use Git's
> +# build variables and operating system detection.  Hence all files in
> +# CGit's directory must be prefixed with "../".
> +include Makefile
> +
> +CGIT_PREFIX = ../
> +
> +# The CGIT_* variables are inherited when this file is called from the
> +# main Makefile - they are defined there.
> +
> +$(CGIT_PREFIX)VERSION: force-version
> +	@cd $(CGIT_PREFIX) && ./gen-version.sh "$(CGIT_VERSION)"
> +-include $(CGIT_PREFIX)VERSION
> +.PHONY: force-version
> +
> +# CGIT_CFLAGS is a separate variable so that we can track it separately
> +# and avoid rebuilding all of Git when these variables change.
> +CGIT_CFLAGS += -DCGIT_VERSION='"$(CGIT_VERSION)"'
> +CGIT_CFLAGS += -DCGIT_CONFIG='"$(CGIT_CONFIG)"'
> +CGIT_CFLAGS += -DCGIT_SCRIPT_NAME='"$(CGIT_SCRIPT_NAME)"'
> +CGIT_CFLAGS += -DCGIT_CACHE_ROOT='"$(CACHE_ROOT)"'
> +
> +ifdef NO_C99_FORMAT
> +	CFLAGS += -DNO_C99_FORMAT
> +endif
> +
> +CGIT_OBJS += $(CGIT_PREFIX)cgit.o
> +CGIT_OBJS += $(CGIT_PREFIX)cache.o
> +CGIT_OBJS += $(CGIT_PREFIX)cmd.o
> +CGIT_OBJS += $(CGIT_PREFIX)configfile.o
> +CGIT_OBJS += $(CGIT_PREFIX)html.o
> +CGIT_OBJS += $(CGIT_PREFIX)parsing.o
> +CGIT_OBJS += $(CGIT_PREFIX)scan-tree.o
> +CGIT_OBJS += $(CGIT_PREFIX)shared.o
> +CGIT_OBJS += $(CGIT_PREFIX)ui-atom.o
> +CGIT_OBJS += $(CGIT_PREFIX)ui-blob.o
> +CGIT_OBJS += $(CGIT_PREFIX)ui-clone.o
> +CGIT_OBJS += $(CGIT_PREFIX)ui-commit.o
> +CGIT_OBJS += $(CGIT_PREFIX)ui-diff.o
> +CGIT_OBJS += $(CGIT_PREFIX)ui-log.o
> +CGIT_OBJS += $(CGIT_PREFIX)ui-patch.o
> +CGIT_OBJS += $(CGIT_PREFIX)ui-plain.o
> +CGIT_OBJS += $(CGIT_PREFIX)ui-refs.o
> +CGIT_OBJS += $(CGIT_PREFIX)ui-repolist.o
> +CGIT_OBJS += $(CGIT_PREFIX)ui-shared.o
> +CGIT_OBJS += $(CGIT_PREFIX)ui-snapshot.o
> +CGIT_OBJS += $(CGIT_PREFIX)ui-ssdiff.o
> +CGIT_OBJS += $(CGIT_PREFIX)ui-stats.o
> +CGIT_OBJS += $(CGIT_PREFIX)ui-summary.o
> +CGIT_OBJS += $(CGIT_PREFIX)ui-tag.o
> +CGIT_OBJS += $(CGIT_PREFIX)ui-tree.o
> +CGIT_OBJS += $(CGIT_PREFIX)vector.o
> +
can we do a patsubst instead? Something like:

OBJECTS =
OBJECTS += cgit.o
.... and so on

CGIT_OBJS = $(OBJECTS:$(CGIT_PREFIX)%=%)

_or_ 

CGIT_OBJS = $(patsubst %,$(CGIT_PREFIX)%,$(OBJECTS))

> +ifeq ($(wildcard $(CGIT_PREFIX).depend),)
> +missing_dep_dirs += $(CGIT_PREFIX).depend
> +endif
> +
> +$(CGIT_PREFIX).depend:
> +	@mkdir -p $@
> +
> +$(CGIT_PREFIX)CGIT-CFLAGS: FORCE
> +	@FLAGS='$(subst ','\'',$(CGIT_CFLAGS))'; \
> +	    if test x"$$FLAGS" != x"`cat ../CGIT-CFLAGS 2>/dev/null`" ; then \
> +		echo 1>&2 "    * new CGit build flags"; \
> +		echo "$$FLAGS" >$(CGIT_PREFIX)CGIT-CFLAGS; \
> +            fi
> +
> +$(CGIT_OBJS): %.o: %.c GIT-CFLAGS $(CGIT_PREFIX)CGIT-CFLAGS $(missing_dep_dirs)
> +	$(QUIET_CC)$(CC) -o $*.o -c $(dep_args) $(ALL_CFLAGS) $(EXTRA_CPPFLAGS) $(CGIT_CFLAGS) $<
> +
> +$(CGIT_PREFIX)cgit: $(CGIT_OBJS) GIT-LDFLAGS $(GITLIBS)
> +	$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS)
> -- 
> 1.8.2.rc1.339.g93ec2c9
> 
> 
> _______________________________________________
> cgit mailing list
> cgit at hjemli.net
> http://hjemli.net/mailman/listinfo/cgit




More information about the CGit mailing list