X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fyoink;a=blobdiff_plain;f=Makefile;h=dfdfaeb072e71a2ed66dabb04fbf4f3b563b6ed3;hp=ccf61fa0150b4ba4bbe37bd59b1a814ed6b94e4e;hb=8089e9f26d9fe0bd6037f2402a211d29492ad7c6;hpb=5cec68537a631d85e4dec5219f5e0edad1167b10 diff --git a/Makefile b/Makefile index ccf61fa..dfdfaeb 100644 --- a/Makefile +++ b/Makefile @@ -1,207 +1,323 @@ # # Yoink -# Use this file with make to compile and install Yoink. +# Use this file with GNU make to compile and install Yoink. # -# This makefile supports these targets: -# all, install, clean, distclean, run, debug, dist, dist-gzip, dist-bzip2 -# -# This build system incorporates the ideas written by Emile van Bergen: -# http://www.xs4all.nl/~evbergen/nonrecursive-make.html -# - -# Set this to `yes' to echo each build command in full. -verbose := no +# Set V to `1' to echo each build command in full. The default behavior will +# keep output minimal so that warnings are clearly visible. +V = 0 -# -# Include the configuration file, config.mk. -# +SHELL = /bin/sh -SHELL := /bin/sh -have_config := $(wildcard config.mk) -ifneq ($(strip $(have_config)),) -include config.mk +ifeq (menuconfig,$(MAKECMDGOALS)) +# If all we want is to bring up the configure script, then we really don't +# need to define any other functions or recipes process anything else. +menuconfig: + ./configure --interactive +.PHONY: menuconfig else -$(error You must run the configure script before you can make anything) -endif +# Recipe to create `config.h' which is included by some source files. +config.h: config.mk + $(Q)$(configure) --export-header=$@ -# -# Declare the default targets and implicit rules. -# - -.PHONY: all -all: all_ +# Recipe to create `config.sed' which is used by some recipes to search and +# replace certain terms in some files, usually with a `.in' suffix. +config.sed: config.mk + $(Q)$(configure) --export-terms=$@ -.SUFFIXES: -.SUFFIXES: .a .c .cc .cpp .in .o .rc +# Recipe to create `config.mk' which is the makefile with important configure +# options set. +config.mk: + $(Q)$(configure) --interactive --print-instructions=no -# -# Define some useful functions. -# +# Include the configure makefile; fail if it doesn't exist. +include config.mk -add_exe_suffix = $(addsuffix $(EXEEXT),$1) -remove_silencer = $(1:@%=%) +# This simple variable will be appended with targets which must be built +# before the `install-data' target. +data_targets := -# -# Include the subdirectories--order is not important. -# +# This simple variable will be appended with targets which must be built +# before the `install-exec' target. +exec_targets := -dir := src -include $(dir)/rules.mk +# This simple variable will be appended with subdirectories which contain +# rules as well as their corresponding subdirectories under the build +# directory, any directory which might have files to be installed. +subdirs := -dir := data -include $(dir)/rules.mk +# Function to include rules from subdirectories. This is the core of the +# non-recursive make method this build system uses. It works by managing +# several stacks and helping to append the appropriate values to the simple +# variables defined above. +define include_func = +ifeq (,$$d) +dir := $1 +else +dir := $$d/$1 +endif +sp := $$(sp).x +dirstack_$$(sp) := $$d +datstack_$$(sp) := $$(data) +exestack_$$(sp) := $$(exec) +d := $$(dir) +data := +exec := +include $$(dir)/rules.mk +subdirs += $$d $$b +data := $$(sort $$(data) $$(mandir_$$b) $$(datadir_$$b) $$(pkgdatadir_$$b) $$(desktop_$$b)) +exec := $$(sort $$(exec) $$(bindir_$$b) $$(libdir_$$b)) +deps := $$(filter %.d,$$(call depfile,$$(exec))) +clean := $$(clean) $$(deps) $$(exec) $$(data) +DEPFILE := $$(DEPFILE) $$(deps) +data_targets += $$(data) +exec_targets += $$(exec) +d := $$(dirstack_$$(sp)) +data := $$(datstack_$$(sp)) +exec := $$(exestack_$$(sp)) +sp := $$(basename $$(sp)) +endef +include = $(foreach i,$1,$(eval $(call include_func,$i))) + +# These shortcut variables are meant to be used to simplify included rules. +builddir = build/obj +b = $(builddir)/$(d) +this = $(d)/rules.mk + +# Function to convert object file paths to dependency file paths. This also +# supports pre-compiled header files. +depfile = $(patsubst %.h.gch,%.d,$(patsubst %.hh.gch,%.d,$(1:%.o=%.d))) + +# Determine the suffix that installed manual pages should have. +ifeq (gzip,$(manCompression)) +MANEXT=.gz +else +ifeq (bzip2,$(manCompression)) +MANEXT=.bz2 +endif +endif -dir := doc -include $(dir)/rules.mk +# Now do the actual inclusion of the rules from these subdirectories. +$(call include,src data doc) +# Also include platform-specific rules, if they exist. +-include build/arch/$(platform)/rules.mk -# -# Define some common rules. -# +# Handle automatic tracking of dependencies, if enabled. This adds overhead +# and should be disabled if not needed. +ifeq (true,$(tracking)) +PKG_CFLAGS += -MT $@ -MMD -MP -MF $(call depfile,$@) +-include $(DEPFILE) +endif -ifeq ($(DEP_TRACKING),true) -COMPILE = ./tools/compile.lua +# Handle the inclusion of a PCH file, if enabled. Using a PCH file can +# improve build times in some (but not all) cases. The rules should also +# define the `pchfile' variable to the path of the PCH file. Only one PCH +# file can be used. If the PCH file has a `.h' suffix, it is included only +# when compiling C sources, otherwise it will be included only when compiling +# C++ sources. +ifeq (true,$(pch)) +ifneq (,$(pchfile)) +PCH_FLAGS = -Winvalid-pch -include $(pchfile) +endif endif -COMMAND_CC = $(COMPILE) $(CC) $(CFLAGS) $(CF_TGT) -o $@ -c $< -COMMAND_CXX = $(COMPILE) $(CXX) $(CXXFLAGS) $(CF_TGT) -o $@ -c $< -COMMAND_LD = $(CC) $(LDFLAGS) $(LF_TGT) -o $@ $^ $(LL_TGT) $(LIBS) -COMMAND_LDX = $(CXX) $(LDFLAGS) $(LF_TGT) -o $@ $^ $(LL_TGT) $(LIBS) -COMMAND_CCLD = $(COMPILE) $(CC) $(CFLAGS) $(CF_TGT) $(LDFLAGS) $(LF_TGT) -o $@ $< $(LL_TGT) $(LIBS) -COMMAND_CXXLD = $(COMPILE) $(CXX) $(CXXFLAGS) $(CF_TGT) $(LDFLAGS) $(LF_TGT) -o $@ $< $(LL_TGT) $(LIBS) -COMMAND_AR = $(AR) rcs $@ $^; $(RANLIB) $@ -COMMAND_RC = $(WINDRES) $(DDEFINES) $(DF_TGT) -o $@ -i $< -COMMAND_INSTALL = ./tools/install.sh -m $1 $2 -d $3 -COMMAND_RM = rm -f $1 -COMMAND_IN = sed -f config.sed <"$1" >"$2" - -ifeq ($(verbose),yes) -DO_CC = $(COMMAND_CC) -DO_CXX = $(COMMAND_CXX) -DO_LD = $(COMMAND_LD) -DO_LDX = $(COMMAND_LDX) -DO_CCLD = $(COMMAND_CCLD) -DO_CXXLD = $(COMMAND_CXXLD) -DO_AR = $(COMMAND_AR) -DO_RC = $(COMMAND_RC) -DO_INSTALL = $(COMMAND_INSTALL) -DO_RM = $(COMMAND_RM) -DO_IN = $(COMMAND_IN) -SHELL_LINE_PREFIX = +# Include current directory to allow sources to include config.h. +override CPPFLAGS += -I. -DHAVE_CONFIG_H=1 + +# The target C++ flags should mirror the target C flags by default. +TGT_CXXFLAGS = $(TGT_CFLAGS) + +# Define the default flags passed to the library archiver. +ARFLAGS = rc + +# Define the default install program. +INSTALL = install + +# Define the `tarname' to be used as a base filename for distributable +# archives. +tarname = $(TARNAME)-$(VERSION) + +# Define the commands needed to make several different types of files. Don't +# used these commands directly because they don't account for verbosity; +# instead use the commands without the `cmd_' prefix (defined below). +cmd_compile_c = $(CC) $(PKG_CFLAGS) $(TGT_CFLAGS) $(PCH_CFLAGS) $(CFLAGS) $(MYCFLAGS) $(CPPFLAGS) \ + $(TARGET_ARCH) -c $(OUTPUT_OPTION) $< +cmd_compile_cc = $(CXX) $(PKG_CXXFLAGS) $(TGT_CXXFLAGS) $(PCH_CXXFLAGS) $(CXXFLAGS) $(MYCXXFLAGS) $(CPPFLAGS) \ + $(TARGET_ARCH) -c $(OUTPUT_OPTION) $< +cmd_link_c = $(CC) $(PKG_CFLAGS) $(TGT_CFLAGS) $(PCH_CFLAGS) $(CFLAGS) $(MYCFLAGS) $(CPPFLAGS) \ + $(PKG_LDFLAGS) $(TGT_LDFLAGS) $(LDFLAGS) $(MYLDFLAGS) \ + $(TARGET_ARCH) $^ $(LOADLIBES) $(PKG_LDLIBS) $(TGT_LDLIBS) $(LDLIBS) -o $@ +cmd_link_cc = $(CXX) $(PKG_CXXFLAGS) $(TGT_CXXFLAGS) $(PCH_CXXFLAGS) $(CXXFLAGS) $(MYCXXFLAGS) $(CPPFLAGS) \ + $(PKG_LDFLAGS) $(TGT_LDFLAGS) $(LDFLAGS) $(MYLDFLAGS) \ + $(TARGET_ARCH) $^ $(LOADLIBES) $(PKG_LDLIBS) $(TGT_LDLIBS) $(LDLIBS) -o $@ +cmd_compile_pch = $(CC) $(PKG_CFLAGS) $(TGT_CFLAGS) $(CFLAGS) $(MYCFLAGS) $(CPPFLAGS) \ + $(TARGET_ARCH) -c $(OUTPUT_OPTION) $< +cmd_compile_pchh = $(CXX) $(PKG_CXXFLAGS) $(TGT_CXXFLAGS) $(CXXFLAGS) $(MYCXXFLAGS) $(CPPFLAGS) \ + $(TARGET_ARCH) -c $(OUTPUT_OPTION) $< +cmd_ar = $(AR) $(ARFLAGS) $@ $^; $(RANLIB) $@ +cmd_compile_rc = $(WINDRES) $(CPPFLAGS) $(TARGET_ARCH) $(OUTPUT_OPTION) -i $< +cmd_sed = sed -f config.sed <$< >$@ +cmd_gzip = gzip -c $< >$@ +cmd_bzip2 = bzip2 -c $< >$@ +cmd_xxd = id=$(subst .,_,$(notdir $<)); \ + printf "\#include \nsize_t\tdata_%s_size = %d;\nchar\tdata_%s[] = {\n" \ + $$id $$(wc -c <$<) $$id >$@; \ + xxd -i <$< >>$@; \ + printf ", 0x00\n};\n" >>$@ +cmd_configure = ./configure + +# Define some useful functions. Don't use these functions directly because +# they don't account for verbosity; instead use the functions without the +# `func_' prefix (defined below). +func_remove = rm -f $1 +func_install = mkdir -p $(DESTDIR)$3 && $(INSTALL) -m $1 $2 $(DESTDIR)$3 +func_dist = git archive HEAD --prefix='$(tarname)/' | $1 >"$(tarname).tar.$2" && \ + (openssl md5 "$(tarname).tar.$2" 2>/dev/null || \ + md5 "$(tarname).tar.$2" 2>/dev/null || \ + md5sum "$(tarname).tar.$2" 2>/dev/null) + +# These commands and functions should be used in most recipes to compile +# sources, link objects, compress files, create distfiles, install files, etc. +compile_c = $(call func_print,CC,$@) $(cmd_compile_c) +compile_cc = $(call func_print,CXX,$@) $(cmd_compile_cc) +compile_rc = $(call func_print,RC,$@) $(cmd_compile_rc) +link_c = $(call func_print,LINK,$@) $(cmd_link_c) +link_cc = $(call func_print,LINK,$@) $(cmd_link_cc) +compile_pch = $(call func_print,CC,$@) $(cmd_compile_pch) +compile_pchh = $(call func_print,CXX,$@) $(cmd_compile_pchh) +ar = $(call func_print,AR,$@) $(cmd_ar) +sed = $(call func_print,SED,$@) $(cmd_sed) +gzip = $(call func_print,GZIP,$@) $(cmd_gzip) +bzip2 = $(call func_print,BZIP2,$@) $(cmd_bzip2) +xxd = $(call func_print,XXD,$@) $(cmd_xxd) +configure = $(call func_print,MAKE,$@) $(cmd_configure) +dist = $(call func_print,DIST,$1) $(func_dist) +remove = $(call func_print,RM,$1) $(func_remove) +install = $(call func_print,CP,$(DESTDIR:%/=%)$(3:%/=%)/$(notdir $2)) $(func_install) + +# The mechanism used by this makefile to handle verbosity simply requires (by +# convention) commands in rules to be prefixed with `$Q' and the commands and +# functions defined above will then print a single line describing the command +# instead of the entire command. +ifeq (1,$V) +Q = +func_print = else -DO_CC = @echo " CC $@"; $(COMMAND_CC) -DO_CXX = @echo " CXX $@"; $(COMMAND_CXX) -DO_LD = @echo " LD $@"; $(COMMAND_LD) -DO_LDX = @echo " LD $@"; $(COMMAND_LDX) -DO_CCLD = @echo " CCLD $@"; $(COMMAND_CCLD) -DO_CXXLD = @echo " CXXLD $@"; $(COMMAND_CXXLD) -DO_AR = @echo " AR $@"; $(COMMAND_AR) -DO_RC = @echo " RC $@"; $(COMMAND_RC) -DO_INSTALL = @echo " CP $2"; $(COMMAND_INSTALL) -DO_RM = @echo " RM $1"; $(COMMAND_RM) -DO_IN = @echo " MAKE $2"; $(COMMAND_IN) -SHELL_LINE_PREFIX = @ +Q = @ +func_print = printf "\x20\x20$1\t%s\n" $2; endif -# -# Define the implicit rules. -# - +# Define the implicit rules. Targets and sources which match do not need to +# be explicitly stated in the rule definitions. %.o: %.c - $(DO_CC) + $(Q)$(compile_c) +%.h.gch: %.h + $(Q)$(compile_pch) %.o: %.cc - $(DO_CXX) + $(Q)$(compile_cc) %.o: %.cpp - $(DO_CXX) + $(Q)$(compile_cc) +%.hh.gch: %.hh + $(Q)$(compile_pchh) %.o: %.rc - $(DO_RC) -%: %.o - $(DO_LD) -%: %.c - $(DO_CCLD) -%: %.cc - $(DO_CXXLD) -%: %.cpp - $(DO_CXXLD) -%.a: %.o - $(DO_AR) + $(Q)$(compile_rc) %: %.in - $(call DO_IN,$<,$@) - - -# -# Define the phony targets. -# - -.PHONY: clean + $(Q)$(sed) +%.gz: % + $(Q)$(gzip) +%.bz2: % + $(Q)$(bzip2) + +# More explicit rules which allow targets in the build directory to be made +# directly. A special rules is also defined to create directories or copy +# files under the build directory to match the structure of the source +# directory. +$(builddir)/%.o: %.cc + $(Q)$(compile_cc) +$(builddir)/%.o: %.cpp + $(Q)$(compile_cc) +$(builddir)/%.o: %.c + $(Q)$(compile_c) +$(builddir)/%.o: %.rc + $(Q)$(compile_rc) +$(builddir)/%: %.in + $(Q)$(sed) +$(builddir)/%.gz: % + $(Q)$(gzip) +$(builddir)/%.bz2: % + $(Q)$(bzip2) +$(builddir)/%: % + $(Q)if [ -d $< ]; then mkdir -p $@; elif [ -f $< ]; then cp -f $< $@; fi + + +# Define the default target(s). This should `make' just about everything. +.DEFAULT_GOAL := +all: $(exec_targets) $(data_targets) + +# Define the recipe to clean the targets. This will remove the target files +# and the empty directories of the build hierarchy. clean: - $(SHELL_LINE_PREFIX)files='$(CLEAN)'; for file in $$files; \ - do \ - $(call remove_silencer,$(call DO_RM,$$file)); \ - done + $(Q)$(foreach f,$(clean),$(call remove,$f);) + $(Q)if [ -d $(builddir) ]; then find $(builddir) -type d -empty -delete; fi -.PHONY: distclean +# Make the project even cleaner by removing files created by configuration. distclean: clean - $(call DO_RM,config.h) - $(call DO_RM,config.mk) - $(call DO_RM,config.sed) - -.PHONY: all_ -all_: $(BINARIES) $(MANPAGES) - -.PHONY: install -install: all - $(SHELL_LINE_PREFIX)files='$(DATAFILES)'; for file in $$files; \ - do \ - full=`echo "$$file" | cut -d\; -f1`; \ - base=`echo "$$file" | cut -d\; -f2`; \ - $(call remove_silencer,$(call DO_INSTALL,644,$$full,$(DESTDIR)$(datadir)$$base)); \ - done - $(SHELL_LINE_PREFIX)files='$(BINARIES)'; for file in $$files; \ - do \ - $(call remove_silencer,$(call DO_INSTALL,755,$$file,$(DESTDIR)$(bindir))); \ - done - $(SHELL_LINE_PREFIX)files='$(MANPAGES)'; for file in $$files; \ - do \ - $(call remove_silencer,$(call DO_INSTALL,644,$$file,$(DESTDIR)$(mandir))); \ - done - -.PHONY: uninstall -uninstall: - $(SHELL_LINE_PREFIX)files='$(BINARIES)'; for file in $$files; \ - do \ - base="/`basename $$file`"; \ - $(call remove_silencer,$(call DO_RM,$(DESTDIR)$(bindir)$$base)); \ - done - $(SHELL_LINE_PREFIX)files='$(DATAFILES)'; for file in $$files; \ - do \ - full="`echo "$$file" | cut -d\; -f1`"; \ - base="`echo "$$file" | cut -d\; -f2`/`basename $$full`"; \ - $(call remove_silencer,$(call DO_RM,$(DESTDIR)$(datadir)$$base)); \ - done - -.PHONY: dist-bzip2 + $(Q)cd build && $(MAKE) clean + $(Q)$(call remove,config.h);$(call remove,config.mk);$(call remove,config.sed) + +# Installation happens in two separated phases, installing the executable +# (i.e. platform-specific) files and installing the data files. +install: install-data install-exec + +# Recipe to install the data files. Right now, that includes files destined +# for `pkgdatadir' and `mandir'. +install-data: $(data_targets) + $(Q)$(foreach d,$(subdirs),$(foreach f,$(pkgdatadir_$d),\ + $(call install,644,$f,$(dir $(f:$d%=$(pkgdatadir)%)));)) + $(Q)$(foreach d,$(subdirs),$(foreach f,$(mandir_$d),\ + $(call install,644,$f,\ + $(dir $(f:$d%=$(mandir)/man$(shell echo "$f" | sed 's/[^.]*\.\([^.]*\).*/\1/')%)));)) + +# Recipe to install executable files. Right now, that includes files destined +# for `bindir'. +install-exec: $(exec_targets) + $(Q)$(foreach d,$(subdirs),$(foreach f,$(bindir_$d),\ + $(call install,755,$f,$(dir $(f:$d%=$(bindir)%)));)) + +# Recipe to install desktop entry file(s) to /usr/share/applications. +install-desktop-entry: $(data_targets) + $(Q)$(foreach d,$(subdirs),$(foreach f,$(desktop_$d),\ + $(call install,644,$f,/usr/share/applications);)) + +# Target used to create distfiles in all the supported compression formats. +dist-all: dist-bzip2 dist-gzip dist-lzma dist-xz + +# Separate targets to create distfiles in the corresponding formats. dist-bzip2: - $(SHELL_LINE_PREFIX)git archive HEAD --prefix='$(TARNAME)/' | bzip2 > "$(TARNAME).tar.bz2" - -.PHONY: dist-gzip + $(Q)$(call dist,bzip2,bz2) dist-gzip: - $(SHELL_LINE_PREFIX)git archive HEAD --prefix='$(TARNAME)/' | gzip > "$(TARNAME).tar.gz" + $(Q)$(call dist,gzip,gz) +dist-lzma: + $(Q)$(call dist,lzma,lzma) +dist-xz: + $(Q)$(call dist,xz,xz) -.PHONY: dist -dist: dist-bzip2 +# The `dist' target will create the distfile in whatever format was set in the +# configuration. +dist: dist-$(archiveFormat) -# -# Prevent make from removing any build targets. -# +# Define which targets do not actually correspond to real files. +.PHONY: all clean distclean +.PHONY: install install-data install-exec install-desktop-entry +.PHONY: dist dist-all dist-gzip dist-bzip2 dist-xz dist-lzma -.SECONDARY: $(CLEAN) +endif # menuconfig