# # @(#)$Id: Makefile,v 1.1 2009/02/26 16:04:13 templon Exp $ # ####################################################### # # General settings # ####################################################### .PHONY: release minorversion majorversion tagversion .PHONY: pack rpm pkg prep clean dist userdoc apidoc check .PHONY: checkmndfiles checkcfgtags checkdprfiles .PHONY: checksrctags header help tagstable markobsolete #################################################################### # Linux specific settings #################################################################### # # CFG_MK = config.mk include $(CFG_MK) _module = $(NAME) _vpfx = $(NAME)_ _vtag = $(subst -,_,$(subst .,_,$(_vpfx)$(VERSION)$(BRANCH))) _prodname = $(NAME)-$(VERSION)$(BRANCH) _prodtar = $(_prodname).src.tgz # if INSTALLPREFIX is defined, install files go there. # Otherwise use TARGPREFIX also as place to install files. ifeq ($(INSTALLPREFIX),) INSTALLPREFIX := $(TARGPREFIX) endif # some SVN commands (ckeckout, update, commit) are by default quiet unless # SVN_VERB is defined _svn := svn --quiet ifneq ($(SVN_VERB),) _svn := svn endif _os := $(shell uname -s) _date := $(shell date '+%d/%m/%y %H:%M') ############################################################################### # Macros ############################################################################### # _error, message # _warn, message # _fatal,err msg,exit code: print "err msg" and quit with "exit code" (the if # clause is just used to group the commands) _fatal = if true; then echo "[FATAL] $(1)">&2; exit $(2); fi _error = echo "[ERROR] $(1)">&2 _warn = echo "[WARN] $(1)">&2 ############################################################################### # SVN ############################################################################### _SVN_BRNCH_SDIR := branches _SVN_TAG_SDIR := tags _SVN_TRNK_SDIR := trunk _SVN_ROOT_PATH := $(shell svn info | grep "Repository Root" | awk '{print $NF}') ################################################################### # Create linux specific build directories ################################################################### envdir:: $(_srcrpmdir) $(_rpmdir) $(_srcrpmdir): _rpmbuild := $(shell [ -x /usr/bin/rpmbuild ] && echo rpmbuild || echo rpm) _builddir := $(shell rpm --eval %_builddir) _specdir := $(shell rpm --eval %_specdir) _sourcedir := $(shell rpm --eval %_sourcedir) _srcrpmdir := $(shell rpm --eval %_srcrpmdir) _rpmdir := $(shell rpm --eval %_rpmdir) _rpm := $(_rpmbuild) --quiet ifneq ($(RPM_VERB),) _rpm := $(_rpmbuild) endif mkdir -p $(_srcrpmdir) $(_rpmdir): mkdir -p $(_rpmdir) #################################################################### # Create new release/version/majorversion #################################################################### # # These targets update the X.Y.Z components of the version in the # config file and then commit the current version, tagging all # files with the release number from the config file. Also # wires the current date and time into the config file. Also # adds an entry to the ChangeLog. # check that the requested operation is allowed: # - refuse to run if SVN passwords/credentials caching is off # - forbid committing in tags/ directory release: config.tmp @echo '${_SVN_ROOT_PATH}' minorversion: _checkop config.tmp @echo '[INFO] increasing minorversion number x..x and timestamp..' @perl $(CFG_MK) -e 'while (<>) ' \ -e '{ s/^(VERSION=\d+\.)(\d+)(\..*)$$/$$1.($$2+1).".0"/e;' \ -e ' s/^(RELEASE=)(\d+)(.*)$$/$$1."1".$$3/e; print; }' @$(MAKE) tagversion majorversion: _checkop config.tmp @echo '[INFO] increasing majorversion number .x.x and timestamp..' @perl $(CFG_MK) -e 'while (<>)' \ -e '{ s/^(VERSION=)(\d+)(\..*)$$/$$1.($$2+1).".0.0"/e;' \ -e ' s/^(RELEASE=)(\d+)(.*)$$/$$1."1".$$3/e; print; }' @$(MAKE) tagversion config.tmp: $(CFG_MK) @$(_svn) update . @sed <$(CFG_MK) >config.tmp '/^DATE=/d' @echo 'DATE=$(_date)' >>config.tmp @cp $(CFG_MK) $(CFG_MK)~ tagversion: _checkop @echo "[INFO] svn committing new release: $(VERSION)" @rm -f config.tmp @perl -e '$$date=`date +%Y-%m-%d`;' \ -e 'chomp($$date);' \ -e '$$login=getlogin();' \ -e '$$logstr="";' \ -e '$$logstr=(getpwnam($$login))[6] if defined $$login;' \ -e 'print $$date." $$logstr\n\n"; '\ -e 'print "\t* Release: $(NAME)-$(VERSION)\n";' >ChangeLog.tmp @if [ "$(EDITOR)" -a -x "$(EDITOR)" ]; then \ perl -e 'print "\t- [your comment here]"' >>ChangeLog.tmp; \ $(EDITOR) ChangeLog.tmp; \ perl -e '$$/=undef; $$text=<>; $$text =~ s/\s*\n*$$//s;' \ -e 'print "$$text\n\n"' < ChangeLog.tmp > ChangeLog.tmp2; \ mv ChangeLog.tmp2 ChangeLog.tmp; \ else \ echo "[INFO] Enter ChangeLog comment (hit CTRL+D to stop):"; \ perl -e '$$text=""; while(<>) { $$text .= "\t$$_" };' \ -e '$$text =~ s/^\s*(.+?)\s*\n*$$/$$1/s;' \ -e 'chomp($$text); print "\t- $$text\n\n"' >>ChangeLog.tmp; \ fi @if [ ! -r ChangeLog ] ; then touch ChangeLog ; $(_svn) add ChangeLog ; fi @cp ChangeLog.tmp /tmp/ChangeLog.tmp.$$$ @cat ChangeLog >>ChangeLog.tmp @mv ChangeLog.tmp ChangeLog @$(_svn) commit -F /tmp/ChangeLog.tmp.$$$ @rm -f /tmp/ChangeLog.tmp.$$$ @$(MAKE) _tag_dir=$(_vtag) svntag @$(MAKE) _tag_dir=latest _trg_tag=$(_vtag) svnextag @$(MAKE) tagstable # auxiliary target to build an SVN tag. Input parameter is _tag_dir, which # is the leaf subdirectory (intermediate subdirectories are built transparently); # _co_root is the checkout root, # _co_locl is the local path to the module in the checkout # _co_subd is the sub-path to the module in the checkout # that is: # $pwd == $_co_root/$_co_locl == $_co_root/$_co_subd/$_module # _svn_root = $(shell svn info | sed -nr 's/^.+Root:\s+(\S+)$$/\1/ p') _svn_url = $(shell svn info | sed -nr 's/^URL:\s+(\S+)$$/\1/ p') _co_locl = $(shell echo $(_svn_url) | sed -nr 's%^\S+?/$(_SVN_TRNK_SDIR)/%% p') _co_subd = $(shell echo $(_co_locl) | sed -nr 's%/$(_module)$$%% p') # don't ask me why this doesn't work... # _co_root = $(shell echo -n $(PWD) |\ # sed -r 's%^(.+?)/(\S*$(_SVN_TRNK_SDIR)/)?$(_co_locl)$$%\1%' | sed -r 's%/*$$%%') _co_root = $(shell pwd | \ perl -e '$$a=<>; $$a=~s%^(\S+?)/([^/]*$(_SVN_TRNK_SDIR)/)?$(_co_locl)$$%$$1%; print $$a' |\ sed -r 's%/*$$%%') ifneq ($(QTTR_CO_ROOT),) _co_root = $(QTTR_CO_ROOT) endif svntag: _checkop @if [ "$(DEBUG)" ]; then\ echo "[DEBUG] _svn_root=$(_svn_root)" >&2;\ echo "[DEBUG] _svn_url=$(_svn_url)" >&2;\ echo "[DEBUG] _co_locl=$(_co_locl)" >&2;\ echo "[DEBUG] _co_subd=$(_co_subd)" >&2;\ echo "[DEBUG] _co_root=$(_co_root)" >&2;\ fi @[ "$(_tag_dir)" ] || $(call _fatal,no tag directory specified,1) @[ "$(_co_root)" -a "$(_svn_root)" ]\ || $(call _fatal,checkout and/or SVN root not defined,2) @echo "[INFO] svn tagging new release: $(_tag_dir)" @src_path=$$PWD;\ dst_url=$(_svn_root)/$(_SVN_TAG_SDIR)/$(_co_subd)/$(_module);\ dst_path=$(_co_root)/$(_SVN_TAG_SDIR)/$(_co_subd)/$(_module);\ [ "$(DEBUG)" ] && echo "[DEBUG] dst_url=$$dst_url" >&2;\ [ "$(DEBUG)" ] && echo "[DEBUG] dst_path=$$dst_path" >&2;\ aux=$(_co_subd);\ [ "$(DEBUG)" ] && echo "[DEBUG] aux=$$aux" >&2;\ saux='';\ made_sdir=0;\ tag_mod_root='';\ while [ "$$aux" ]; do\ sdir=`echo -n $$aux | sed -nr 's%^([^/]+).*?$$%\1% p'`;\ [ $$made_sdir -eq 0 ] && tag_mod_root=$$sdir;\ [ "$(DEBUG)" ] && echo "[DEBUG] sdir=$$sdir" >&2;\ saux=$$saux/$$sdir;\ dst_surl=$(_svn_root)/$(_SVN_TAG_SDIR)/$$saux;\ [ "$(DEBUG)" ] && echo "[DEBUG] dst_surl=$$dst_surl" >&2;\ if (svn info $$dst_surl 2>&1 | egrep "\(Not a valid URL\)") >/dev/null; then\ $(_svn) mkdir $$dst_surl -m "Made directory $(_SVN_TAG_SDIR)$$saux" \ || $(call _fatal,$$dst_surl: cant make svn dir,3);\ fi;\ aux=`echo -n $$aux | sed -nr "s%^$$sdir/%% p"`;\ [ "$(DEBUG)" ] && echo "[DEBUG] aux=$$aux" >&2;\ made_sdir=1;\ done;\ if (svn info $$dst_url 2>&1 | egrep "\(Not a valid URL\)") >/dev/null; then\ [ "$(DEBUG)" ] && echo "[DEBUG] svn mkdir $$dst_url" >&2;\ $(_svn) mkdir $$dst_url -m "Made directory $(_SVN_TAG_SDIR)/$(_co_subd)/$(_module)"\ || $(call _fatal,$$dst_url: cant make svn dir,4);\ fi;\ [ "$(DEBUG)" ] && echo "[DEBUG] svn copy $$src_path $$dst_url/$(_tag_dir)" >&2;\ $(_svn) copy $$src_path $$dst_url/$(_tag_dir) -m "Added tag $(_module)/$(_tag_dir)" \ || $(call _fatal,$$src_path: cant svn copy to $$dst_url/$(_tag_dir),5);\ [ "$(DEBUG)" ] && echo "[DEBUG] svn co $$dst_url/$(_tag_dir) $$dst_path/$(_tag_dir)" >&2;\ $(_svn) checkout $$dst_url/$(_tag_dir) $$dst_path/$(_tag_dir) \ || $(call _fatal,$$dst_url/$(_tag_dir): cant svn check out,6) svnextag: _checkop @[ "$(_tag_dir)" ] || $(call _fatal,no tag directory specified,1) @[ "$(_trg_tag)" ] || $(call _fatal,no target tag specified,2) @echo "[INFO] svn tagging external reference: $(_tag_dir) -> $(_trg_tag)" @[ "$(_co_root)" -a "$(_svn_root)" ]\ || $(call _fatal,checkout and/or SVN root not defined,3) @src_sdir=$(_SVN_TAG_SDIR)/$(_co_subd)/$(_module)/$(_trg_tag);\ src_url=$(_svn_root)/$$src_sdir;\ src_path=$(_co_root)/$$src_sdir;\ dst_sdir=$(_SVN_TAG_SDIR)/$(_co_subd)/$(_module)/$(_tag_dir);\ dst_url=$(_svn_root)/$$dst_sdir;\ dst_path=$(_co_root)/$$dst_sdir;\ if (svn info $$dst_url 2>&1 | egrep "\(Not a valid URL\)") >/dev/null; then\ $(_svn) mkdir $$dst_url -m "Made directory $$dst_surl"\ || $(call _fatal,$$dst_surl: cant make svn dir,4);\ cd $(_co_root)/$(_SVN_TAG_SDIR);\ $(_svn) checkout $$dst_url $$dst_path \ || $(call _fatal,$$dst_url: cant svn check out,5);\ else\ $(_svn) checkout $$dst_url $$dst_path \ || $(call _fatal,$$dst_url: cant svn check out,6);\ $(_svn) propdel svn:externals $$dst_path \ || $(call _fatal,$$dst_path: cant delete svn:externals,7);\ rm -rf $$dst_path/*;\ fi;\ ext_rev=`svn info $$src_url | sed -nr 's%^Revision:\s+(\S+)$$%\1% p'`;\ [ "$$ext_rev" ] || $(call _fatal,cant determine external revision,8);\ $(_svn) propset svn:externals "$(_trg_tag) -r$$ext_rev $$src_url" $$dst_path \ || $(call _fatal,$$dst_path: cant set svn:externals,9);\ $(_svn) commit $$dst_path -m "Added tag $(_module)/$(_tag_dir) -> $(_trg_tag)" \ || $(call _fatal,$$dst_path: cant svn commit,10);\ $(_svn) update $$dst_path || $(call _fatal,$$dst_path: cant svn update,11) tagstable: _checkop @echo "[INFO] tagging 'stable' release" @prompt='Do you want to tag this release as 'stable'? [no]: ';\ while read -p "$$prompt" ans || exit 1; do\ [ -z $$ans ] && ans='no';\ case $$ans in\ [Yy]|[Yy]es)\ _tag_dir=stable _trg_tag=$(_vtag) $(MAKE) svnextag;\ break;\ ;;\ [Nn]|[Nn]o)\ break;\ ;;\ *)\ prompt='Answer either "yes" or not at all: ';\ esac;\ done # mark as OBSOLETE (no SVN tag is added). A message to be added to config.mk # can be passed through the variable OBSOLETE_MSG markobsolete: _checkop @[ -w config.mk ]\ || $(call _fatal,config.mk: file missing or not writable,1) @if [ "`sed -nr '/^\s*OBSOLETE/ p' config.mk`" ]; then\ $(call _fatal,already marked as OBSOLETE,2);\ fi @echo "[INFO] marking as OBSOLETE" @obs_msg='1';\ if [ ! -z "$$OBSOLETE_MSG" ]; then\ obs_msg="$$OBSOLETE_MSG";\ fi;\ echo OBSOLETE="$$obs_msg" >> config.mk @$(_svn) commit -m 'Module marked as OBSOLETE'\ || $(call _fatal,cant svn commit,3) #################################################################### # Build distributions in tar & RPM/PKG format #################################################################### # # These targets make distribution tar files and PKGs/RPMs from the # CVS repository, using the version declared in the config file. # The checked-out files in the current directory are neither # modified, nor read (apart from the config file). # # "pack" and "rpm" built from the sources in the current directory. # # # The prep:: target allows the including makefile to specify actions # required to process the files at distribution pack time. # # These targets make distribution tar files and PKGs/RPMs based on the # checked-out sources in the current directory. No connection to # the CVS repository is required, and the files do not need to be # committed. The RPM version numbers are generated from the # version number specified in the config file. # pack: envdir @echo packing distribution... @rm -rf $(_builddir)/$(_prodname) @rm -f $(_sourcedir)/$(_prodtar) @mkdir -p $(_builddir)/$(_prodname) @find . -path '*CVS*' -prune -o -type f -print >files.tmp @tar cfT - files.tmp |(cd $(_builddir)/$(_prodname) ; tar xf -) @rm -f files.tmp @[ ! -f specfile.spec -a -f specfile.cin ] \ && cp specfile.cin \ $(_builddir)/$(_prodname)/specfile.spec \ || : ; @cp cl2rpm \ $(_builddir)/$(_prodname)/ > /dev/null 2>&1 \ || : ; @cd $(_builddir)/$(_prodname) ; \ sed <$(CFG_MK) >config.tmp \ -e 's%^RELEASE=\(.*\)%RELEASE=\1%' \ -e 's%^VERSION=.*%&$(BRANCH)%' ; \ mv config.tmp $(CFG_MK) ; \ echo 'TARFILE=$(_prodtar)' >>$(CFG_MK) ; \ echo 'PROD=\#' >>$(CFG_MK) ; \ $(MAKE) config.sh ;\ $(MAKE) prep ;\ test -n "$(_test_dep)" && rm -f $(_test_dep) ;\ rm -f config.sh @cd $(_builddir) ; tar czf $(_sourcedir)/$(_prodtar) $(_prodname) filelist: install # # ---- DO NOT MODIFY BELOW THIS LINE --- NEEDED FOR SPECFILE # @find $(INSTALLPREFIX) -type d | sed -e 's^$(INSTALLPREFIX)g' -e 's/^/%dir /' >> $(INSTALLPREFIX)/.filelist @find $(INSTALLPREFIX) ! -type d -a ! -name ".filelist" | sed -e 's^$(INSTALLPREFIX)g' >> $(INSTALLPREFIX)/.filelist @echo File found in distribution @cat $(INSTALLPREFIX)/.filelist spec: pack @echo generating specfile.spec ... @cd $(_builddir)/$(_prodname) ; \ $(MAKE) config.sh ;\ ./config.sh $(_specdir)/$(_prodname).spec @test -f ChangeLog && \ cl2rpm ChangeLog \ >>$(_specdir)/$(_prodname).spec || true rpm: spec @echo building rpm ... @cd $(_specdir) ; $(_rpmbuild) -ba $(_specdir)/$(_prodname).spec pkg: spec @echo building pkg ... @cd $(_specdir) ; $(_pkgbuild) -f $(_specdir)/$(_prodname).spec prep:: ##################################################################### # Create substitution script #################################################################### # # This target reads the config file and creates a shell script which # can substitute variables of the form @VAR@ for all config # variables VAR. The messing around with the temporary makefile is # to ensure that any recursive or external references in the # variable values are evaluated by "make" in the same context as # when the config file is included in the makefile. config.sh: Makefile $(_test_dep) @cp /dev/null makefile.tmp @echo include $(CFG_MK) >>makefile.tmp @echo dumpvars: >>makefile.tmp @cat $(CFG_MK) paths.mk | \ perl >>makefile.tmp -e 'my $$fmt = "\t\@echo \"-e \\\"s\@%s\@\$$(%s)g\\\" \\\\\"" ; while (<>) { $$v{$$1}=1 if /^([A-Za-z0-9_]+)\s*:?=.*$$/; } map { printf "$$fmt >>config.sh\n", $$_, $$_; } sort(keys(%v)); print "\n"; ' @echo '#!/bin/sh' >config.sh @echo 'sed \' >>config.sh @$(MAKE) -f makefile.tmp dumpvars >/dev/null @echo ' -e "s/\@MSG\@/ ** Generated file : do not edit **/"'>>config.sh @chmod oug+x config.sh @rm makefile.tmp #################################################################### # Configure #################################################################### %:: %.cin config.sh @echo configuring $@ ... @rm -f $@ ; cp $< $@ @./config.sh <$< >$@ ; chmod oug-w $@ %.$(MANSECT):: %.$(MANSECT).man.cin @echo creating $@ ... @./config.sh <$< >$@ ; chmod oug-w $@ configure: $(shell find . -name \*\.cin 2>/dev/null | sed -e 's/.cin//' || echo) #################################################################### # Install #################################################################### install: configure @echo installing in $(INSTALLPREFIX) ... # # MODIFY location of installed scripts/binaries here # ifdef MYMODS @mkdir -p $(INSTALLPREFIX)/$(MODSUFFIX) for i in $(MYMODS) ; do \ install -m 0444 $$i $(INSTALLPREFIX)/$(MODSUFFIX) ; \ done || : endif ifdef MYDOCS @mkdir -p $(INSTALLPREFIX)/$(DOCSUFFIX) for i in $(MYDOCS) ; do \ install -m 0444 $$i $(INSTALLPREFIX)/$(DOCSUFFIX) ; \ done || : endif ifdef MYCONFIGS @mkdir -p $(INSTALLPREFIX)/$(CONFIGSUFFIX) @for i in $(MYCONFIGS) ; do \ install -m 0444 $$i $(INSTALLPREFIX)/$(CONFIGSUFFIX) ; \ done || : endif ifdef MYSCRIPTS @mkdir -p $(INSTALLPREFIX)/$(SCRIPTSUFFIX) @for i in $(MYSCRIPTS) ; do \ install -m 0555 $$i $(INSTALLPREFIX)/$(SCRIPTSUFFIX) ; \ done || : endif ifdef MYTESTFILES @mkdir -p $(INSTALLPREFIX)/$(TESTSUFFIX) @for i in $(MYTESTFILES) ; do \ install -m 0555 $$i $(INSTALLPREFIX)/$(TESTSUFFIX) ; \ done || : endif ifdef MYPLUGINS @mkdir -p $(INSTALLPREFIX)/$(PLUGINSUFFIX) @for i in $(MYPLUGINS) ; do \ install -m 0555 $$i $(INSTALLPREFIX)/$(PLUGINSUFFIX) ; \ done || : endif #################################################################### clean:: @echo cleaning common files ... @rm -f config.sh config.tex @rm -f `find . -name '*~'` @rm -f `find . -name '*#'` @rm -f `find . -name '*.tmp'` @rm -f `find . -name \*\.cin 2>/dev/null | sed -e 's/.cin//'` dist: pack