# vim:syntax=make:indentexpr=GetMakeIndent(): #----------------------------------------------------------------------- # Copyright (c) 2003 2004 Daan Leijen. # This file is distributed under the wxWindows library license. # See "license.txt" for more details. # # This file contains helper functions for the makefile. #----------------------------------------------------------------------- #-------------------------------------------------------------------------- # Dependencies are handled (almost) automatically: no need for "make depend" :-) # # Makefile implementation notes: # # The dependency (.d) files are generated together with object files using # the compiler -M switch. Such dependency file is later processed # by sed to prepend the proper directory to the target and to move it # into the proper (imports) directory. The way dependency files are handled # was 'discovered' by Tom Tromey, and described by Paul Smith, # see "advanced auto-dependency generation" at: # "http://make.paulandlesley.org/autodep.html" # # (Unfortunately, there are situations where this method doesn't work for Haskell # modules -- but these situations are exteremely rare in practice, nothing that # can't be solved by a "make clean; make" command. I believe that in the end # this method is much more robust than "make depend".) # # We use a single makefile in order to correctly resolve dependencies # between the different projects -- a recursive make fails to do that, # see "recursive make considered harmfull" at: # "http://www.tip.net.au/~millerp/rmch/recu-make-cons-harm.html" # (We might use include files in the future to split this file in smaller chunks.) # # We don't use implicit rules (i.e. "%.o: %.c") as the VPATH mechanism can't # deal with modules with the same name in different directories :-( # # We edit (sed) the haskell dependency files to change dependencies on .hi # files to .o files. We just disregard .hi files and assume they are always # generated together with the .o file. This allows us to leave out the implicit # rule for interface files ("%.hi: %.o"). #-------------------------------------------------------------------------- #-------------------------------------------------------------------------- # Support DESTDIR #-------------------------------------------------------------------------- # append a trailing "/" if DESTDIR is not empty ifneq ($(DESTDIR),) DESTDIR=$(patsubst %/,%,$(DESTDIR))/ endif #-------------------------------------------------------------------------- # Functions on files and directories #-------------------------------------------------------------------------- # create derived file from base name # usage: $(call make-hs,,) # usage: $(call make-objs,,) make-hs =$(patsubst %,$(1)/%.hs,$(2)) make-objs =$(patsubst %,$(1)/%.o,$(2)) make-prof-objs =$(patsubst %,$(1)/%.p_o,$(2)) make-split-objs =$(patsubst %,$(1)/%_split/*.o,$(2)) make-deps =$(patsubst %,$(1)/%.d,$(2)) make-his =$(patsubst %,$(1)/%.hi,$(2)) make-prof-his =$(patsubst %,$(1)/%.p_hi,$(2)) # usage: $(call run-silent,) run-silent =$(1) 1> /dev/null 2> /dev/null run-with-echo =echo "$(1)" && $(1) # usage: $(call relative-to,,) relative-to =$(patsubst $(1)/%,%,$(2)) # usage: $(call relative-fromto,,,) relative-fromto =$(patsubst $(1)%,$(2)%,$(3)) # get directories of files (using 'sort' to get rid of duplicates) dirs-of-files =$(sort $(foreach file,$(1),$(dir $(file)))) # usage: $(call ensure-dir,) # usage: $(call ensure-dirs-of-files,) ensure-dir =if test -d "$(1)" -o "$(1)" = "./"; then :; else $(MKDIR) $(1); fi ensure-dirs =$(foreach dir,$(1),$(call ensure-dir,$(dir)) &&) : ensure-dirs-of-files=$(call ensure-dirs,$(call dirs-of-files,$(1))) # full-remove-dir # safe-remove-dir safe-remove-dir =if test -d $(1); then $(call run-with-echo,$(RMDIR) $(1)); fi safe-remove-dir-contents = if test -d $(1); then $(call run-with-echo,$(RM) -r $(1)/*); fi full-remove-dir =$(call safe-remove-dir-contents,$(1)); $(call safe-remove-dir,$(1)) # safe-move-file(,) # safe-remove-file() safe-move-file =if test -f $(1); then $(call run-with-echo,$(MV) $(1) $(2)); fi safe-remove-file=if test -f $(1); then $(call run-with-echo,$(RM) $(1)); fi safe-remove-files=$(foreach file,$(1),$(call safe-remove-file,$(file)) &&) : # silent-move-file silent-move-file=if test -f $(1); then $(MV) $(1) $(2); fi silent-remove-file=if test -f $(1); then $(RM) $(1); fi #-------------------------------------------------------------------------- # C compilation #-------------------------------------------------------------------------- # make-c-obj(,,) make-c-obj =$(call run-with-echo,$(CXX) -c $(2) -o $(1) $(3)) # compile-c(,,) compile-c =$(call make-c-obj,$(1),$(2),-MD $(3)) && \ $(call silent-move-file,$(notdir $(basename $(1))).d,$(dir $(1))) #-------------------------------------------------------------------------- # Haskell compilation #-------------------------------------------------------------------------- # make-hs-obj(,,,) # silent-move-stubs(,) silent-move-stubs =$(call silent-move-file,$(basename $(2))_stub.h,$(dir $(1))) && \ $(call silent-move-file,$(basename $(2))_stub.c,$(dir $(1))) make-hs-obj =$(call run-with-echo,$(HC) -c $(2) -o $(1) -i$(4) -odir $(4) -hidir $(4) $(3)) # make-hs-deps(,,,,) ifeq ($(GHCOLD),yes) # pre GHC 6.10 make-hs-deps =$(HC) $(2) $(3) -odir $(4) -hidir $(4) $(5) -M -optdep-f -optdep$(basename $(1)).d.in && \ sed -e 's|\.hi|\.o|g' $(basename $(1)).d.in | grep '^$(1)' > $(basename $(1)).d else # GHC 6.10+ and others make-hs-deps =$(HC) $(2) $(3) -odir $(4) -hidir $(4) $(5) -M -dep-makefile -optdep$(basename $(1)).d.in && \ sed -e 's|\.hi|\.o|g' $(basename $(1)).d.in | grep '^$(1)' > $(basename $(1)).d endif # compile-hs(,,,,) compile-hs =$(call make-hs-obj,$(1),$(2),$(3),$(4)) && \ $(call silent-move-stubs,$(1),$(2)) && \ $(call make-hs-deps,$(1),$(2),$(3),$(4),$(5)) ifeq ($(GHCOLD),yes) # pre GHC 6.10 # make-hs-deps(,,,,) make-hs-prof-deps =$(HC) $(2) $(3) -odir $(4) -hidir $(4) $(5) -M -optdep-f -optdep$(basename $(1)).p_d.in && \ sed -e 's|\.o|\.p_o|g' -e 's|\.hi|\.p_o|g' $(basename $(1)).p_d.in | grep '^$(1)' > $(basename $(1)).p_d else # make-hs-deps(,,,,) make-hs-prof-deps =$(HC) $(2) $(3) -odir $(4) -hidir $(4) $(5) -M -dep-makefile -optdep$(basename $(1)).p_d.in && \ sed -e 's|\.o|\.p_o|g' -e 's|\.hi|\.p_o|g' $(basename $(1)).p_d.in | grep '^$(1)' > $(basename $(1)).p_d endif # compile-hs(,,,,) compile-prof-hs =$(call make-hs-obj,$(1),$(2),$(3),$(4)) && \ $(call silent-move-stubs,$(1),$(2)) && \ $(call make-hs-prof-deps,$(1),$(2),$(3),$(4),$(5)) #-------------------------------------------------------------------------- # Linking #-------------------------------------------------------------------------- # make single-object file # combine-objs(,) ifeq ($(TOOLKIT),mac) combine-objs =$(LD) -x -r -o $(1) $(2) else combine-objs =$(LD) -r -o $(1) $(2) endif # create an archive # make-archive(,) make-archive =$(AR) -sr $(1) $(2) make-archive-of-splitobjs =echo $(patsubst %.o,%_split/*.o,$(2)) | xargs -n 25 $(AR) -sr $(1) # update the archive symbol index # make-archive-index() make-archive-index=$(AR) -s $(1) #-------------------------------------------------------------------------- # Installation #-------------------------------------------------------------------------- # install files, keeping directory structure intact (that is why we use 'foreach'). # we circumvent a 'ld' bug on the mac by also re-indexing archives on installation # usage: $(call install-files,,,) # usage: $(call uninstall-files,,,) install-file =echo "install: $(2)" && $(INSTALL) $(1) $(dir $(2)) \ $(if $(filter %.a,$(2)),&& $(call make-archive-index,$(basename $(2)).a)) install-dir =echo "install directory: $(1)" && $(INSTALLDIR) $(1) install-filesx =$(foreach dir,$(call dirs-of-files,$(call relative-fromto,$(1),$(2),$(3))),$(call install-dir,$(dir)) &&) \ $(foreach file,$(3),$(call install-file,$(file),$(call relative-fromto,$(1),$(2),$(file))) &&) \ : install-files =$(call install-filesx,$(patsubst %/,%,$(1)),$(DESTDIR)$(2),$(3)) uninstall-file =if test -f "$(1)"; then echo "uninstall: $(1)"; $(RM) $(1); fi uninstall-dir =if test -d "$(2)" -a "$(2)" != "./"; then echo "uninstall directory: $(1)/$(2)" && $(call run-silent,$(RMDIR) -p $(2)); fi # extremely baroque way of reversing a list of (at most 10) items reverse10 =$(patsubst 9%,%,$(patsubst 8%,%,$(patsubst 7%,%,\ $(patsubst 6%,%,$(patsubst 5%,%,$(patsubst 4%,%,\ $(patsubst 3%,%,$(patsubst 2%,%,$(patsubst 1%,%,\ $(patsubst 0%,%,\ $(sort $(join $(wordlist 1,$(words $(1)),9 8 7 6 5 4 3 2 1 0),$(1)))\ )))))))))) uninstall-filesx=$(foreach file,$(2),$(call uninstall-file,$(file)) &&) \ $(CD) $(1) && \ $(foreach dir,$(call reverse10,$(call dirs-of-files,$(call relative-to,$(1),$(2)))),$(call uninstall-dir,$(1),$(dir)) &&) \ : uninstall-files =$(call uninstall-filesx,$(2),$(call relative-fromto,$(patsubst %/,%,$(1)),$(DESTDIR)$(2),$(3))) # install packages # usage: $(call install-pkg,,) # usage: $(call uninstall-pkg,) install-pkg=cat $(2) | sed -e "s|\$${wxhlibdir}|$(1)|" | $(HCPKG) $(HCPKGOPT) update - uninstall-pkg=if $(call run-silent,$(HCPKG) $(HCPKGOPT) describe $(1)); then echo "unregister package: $(1)" && $(HCPKG) $(HCPKGOPT) unregister $(1); fi #-------------------------------------------------------------------------- # Packaging #-------------------------------------------------------------------------- # copy files. # usage: cp-bindist # use -R switch to copy symbolic links literally instead of following the links. # use -p to preserve file dates to avoid linker bug on macosX with .a files. cp-echox =echo "copy $(1) to $(2)" && $(CP) -p -R $(1) $(2) && : cp-echo =$(foreach file,$(1),$(call cp-echox,$(file),$(2))) cp-fromto =$(call ensure-dirs-of-files,$(call relative-fromto,$(1),$(2),$(3))) && \ $(foreach file,$(3),$(call cp-echo,$(file),$(dir $(call relative-fromto,$(1),$(2),$(file)))) && ) : cp-bindist =$(call cp-fromto,$(patsubst %/,%,$(1)),$(patsubst %/,%,$(2)),$(3)) # usage: $(call cp-relative,,) cp-relative =$(call ensure-dirs-of-files,$(patsubst %,$(1)/%,$(2))) && \ $(foreach file,$(2),$(call cp-echox,$(file),$(1)/$(patsubst %/,%,$(dir $(file)))) && ): cp-hackagedist =$(call cp-relative,$(TOPDIR)/$(HACKAGEDIST-SRCDIR),$(1)) cp-srcdist =$(call cp-relative,$(TOPDIR)/$(SRCDIST-SRCDIR),$(1)) cp-docdist =$(CD) $(1) && $(call cp-relative,$(TOPDIR)/$(DOCDIST-SRCDIR),$(patsubst $(1)/%,%,$(2))) # zip commands zip-add =echo zipping: $(1); $(ZIP) -y -9 $(TOPDIR)/$(1) $(2) zip-add-rec =echo zipping: $(1); $(ZIP) -r -y -9 $(TOPDIR)/$(1) $(2) tgz-add-rec =echo tarring: $(1); tar czf $(TOPDIR)/$(1) $(2)