top := $(shell pwd) all: package # configuration ################################################################ packages := $(filter-out _%,$(shell sed "s/[\# ].*//" conf/sources.mk)) include conf/sources.mk include conf/dependencies.mk export MAVEN_LOCAL_REPO := $(shell cat conf/maven.local.repo.txt) export JAR_DIR := $(shell cat conf/jardir.txt) # download ##################################################################### download: PHONY $(foreach package,$(packages),build/download/$(shell utils/spec2file '$($(package))')) build/download/git/%: .tokens/network if [ -d '$@' ]; then \ cd '$@' && git fetch --all -p; \ else \ mkdir -p '$(@D)' && git clone --mirror '$(shell utils/file2url 'git/$*')' '$@'; \ fi touch '$@' build/download/svn/%: .tokens/network if ! [ -d '$(shell utils/file2base 'svn/$*')' ]; then \ rm -rf '$@' && \ mkdir -p build/download/svn && \ svn checkout --depth=empty \ '$(shell utils/file2url 'svn/$*')' \ build/download/'$(shell utils/file2base 'svn/$*')' && \ cd build/download/'$(shell utils/file2base 'svn/$*')'; \ else \ cd build/download/'$(shell utils/file2base 'svn/$*')' && \ svn update; \ fi && \ svn update --parents '$(shell utils/file2extra 'svn/$*')' touch '$@' build/download/tar/%: .tokens/network mkdir -p '$(@D)' wget -c -O '$@' '$(shell utils/file2url 'tar/$*')' touch '$@' # extract ###################################################################### extract: PHONY $(foreach package,$(packages),build/extract/$(shell utils/spec2file '$($(package))')) # This is a little gross because to get the dependencies right for # `git` and `tar`, we need to do a bit more complex processing of # `%`/`$*`. We could do that with `.SECONDEXPANSION:`, but that is a # whole can of worms. Instead, we use a foreach loop to loop over all # possibilities. `svn` doesn't have this issue, because, unlike `git` # and `tar`, it's `extra` component is present in `build/download`. build/extract/git/%: # magic foreach loop gitref='$(shell utils/file2extra 'git/$*'|cut -d/ -f1)' && \ gitdir=build/extract/'$(shell utils/file2base 'git/$*')'/$${gitref} && \ rm -rf "$$gitdir" && \ { \ mkdir -p "$$(dirname "$$gitdir")" && \ git clone build/download/'$(shell utils/file2base 'git/$*')' "$$gitdir" && \ ( cd "$$gitdir" && git checkout "$$gitref" ); \ } || rm -rf "$$gitdir" touch '$@' build/extract/svn/%: build/download/svn/% rm -rf '$@' mkdir -p '$(@D)' cp -a '$<' '$@' build/extract/tar/%: # magic foreach loop basedir='build/extract/$(shell utils/file2base 'tar/$*')' && \ rm -rf "$$basedir" && \ { \ mkdir -p "$$basedir" && \ ( cd "$$basedir" && tar -m --strip-components 1 -xf '$(top)/$<' ); \ } || rm -rf "$$basedir" $(foreach package,$(packages),$(if $(filter-out svn|%,$($(package))),$(eval \ build/extract/$(shell utils/spec2file '$($(package))'): \ build/download/$(shell utils/file2base "$$(utils/spec2file '$($(package))')") \ ))) # place (patch) ################################################################ place: PHONY $(addprefix build/workdir/,$(packages)) $(addprefix build/workdir/,$(packages)): \ build/workdir/%: rm -rf '$@' mkdir -p '$(@D)' cp -a '$<' '$@' cd '$@' && \ for patch in $(sort $(wildcard $(top)/rules/$*/*.patch)); do \ patch -f -Np1 -i $$patch || { rm -rf '$@'; exit 1; }; \ done && \ if [ -f '$(top)/rules/$*/delete.list' ]; then \ rm -rf -- $$(< '$(top)/rules/$*/delete.list'); \ fi # Loop over our source configuration and set up the dependencies # beteen `build/compile` and `build/extract`. $(foreach package,$(packages),$(eval \ build/workdir/$(package): \ build/extract/$(shell utils/spec2file '$($(package))') \ $(shell find rules/$(package) 2>/dev/null) \ )) # package ###################################################################### package: PHONY $(addprefix build/packages/,$(packages)) package_specific=$(filter $(patsubst rules/%/Makefile,%,$(wildcard rules/*/Makefile)),$(packages)) package_generic =$(filter-out $(patsubst rules/%/Makefile,%,$(wildcard rules/*/Makefile)),$(packages)) dirs2jars = $(if $1,$(shell find $1 -name '*.jar')) deps2jars = $(filter %.jar,$1) $(call dirs2jars,$(filter build/packages/%,$1)) deps2classpath = $(shell echo $(abspath $(call deps2jars,$1)) | tr ' ' :) $(addprefix build/packages/,$(package_specific)): \ build/packages/%: RECURSIVE build/workdir/% rules/%/Makefile CLASSPATH='$(call deps2classpath,$^)' extra_makefiles='$(abspath $(wildcard rules/$*/*.mk))' \ $(MAKE) -C build/workdir/$* -f '$(top)/rules/$*/Makefile' install DESTDIR='$(top)/$@' mkdir -p build/packages/all && lndir -silent '$(top)/$@' build/packages/all $(addprefix build/packages/,$(package_generic)): \ build/packages/%: RECURSIVE build/workdir/% rules/generic/Makefile CLASSPATH='$(call deps2classpath,$^)' extra_makefiles='$(abspath $(wildcard rules/$*/*.mk))' \ $(MAKE) -C build/workdir/$* -f '$(top)/rules/generic/Makefile' install DESTDIR='$(top)/$@' mkdir -p build/packages/all && lndir -silent '$(top)/$@' build/packages/all # boilerplate ################################################################## clean: PHONY rm -rf build/compile build/packages distclean: PHONY rm -rf .tokens build .tokens/%: mkdir -p '$(@D)' && touch '$@' .PHONY: RECURSIVE PHONY