Makefile 7.99 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
# Makefile for single executable C++ project with auto-dependencies and
# multiple build options
# Copyright (C) 2000-2003 Marc Mongenet

###############################################################################
# PROJECT SPECIFIC DEFINITIONS
###############################################################################

# name of file to build
EXE = xgalaga++

# name of manual (leave empty if none)
MANUAL = xgalaga++.6x

# source files suffix (all source files must have the same suffix)
SOURCE_SUFFIX = cc

# C++ compiler
CXX = g++

# source files directory
srcdir = .

# build directory
builddir = .

# installation directories
installprefix = /usr
bindir = $(installprefix)/games
mandir = $(installprefix)/share/man/man6

# preprocessor options to find all included files
33
INC_PATH = -I$(srcdir) -I/usr/local/include
34 35

# libraries link options ('-lm' is common to link with the math library)
36
LNK_LIBS = -lm -lX11 -lXpm -L/usr/local/lib/
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163

# other compilation options
# The high scores file is only writable by the executable and shared
# by all players.
HIGH_SCORES_FILE=/var/games/xgalaga++.scores
#HIGH_SCORES_FILE=.xgalaga++.scores

# This group is used for the executable and high scores file.
# The executable is setgid.
EXE_GROUP=games

COMPILE_OPTS = -DHIGH_SCORES_FILE=$(HIGH_SCORES_FILE)

# basic compiler warning options (for GOAL_EXE)
BWARN_OPTS = -Wall -ansi

# extented compiler warning options (for GOAL_DEBUG)
EWARN_OPTS = $(BWARN_OPTS) -pedantic -W\
	     -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align\
	     -Wwrite-strings -Woverloaded-virtual -Winline

###############################################################################
# INTERNAL DEFINITIONS
# The following definitions are designed to be project neutral.
###############################################################################

# You may freely change the following goal names if you dislike them.
GOAL_DEBUG = debug
GOAL_PROF = prof
GOAL_EXE = all

# build options for GOAL_DEBUG (executable for debugging) goal
ifeq "$(MAKECMDGOALS)" "$(GOAL_DEBUG)"

 # specific options for debugging
 GOAL_OPTS = -g
 # compilation verification options
 WARN_OPTS = $(EWARN_OPTS)
 # optimization options
 OPTIMISE_OPTS =
 # dependencies must be up to date
 CHECK_DEPS = yes

else

 # build options for GOAL_PROF (executable for profiling) goal
 ifeq "$(MAKECMDGOALS)" "$(GOAL_PROF)"

  # specific options for profiling
  GOAL_OPTS = -pg
  # compilation verification options
  WARN_OPTS = $(BWARN_OPTS)
  # optimization options
  OPTIMISE_OPTS = -O
  # dependencies must be up to date
  CHECK_DEPS = yes

 else

  # build options for GOAL_EXE (optimized executable) goal
  ifeq "$(MAKECMDGOALS)" "$(GOAL_EXE)"

   # specific options for optimized executable
   GOAL_OPTS = -s
   # compilation verification options
   WARN_OPTS = $(BWARN_OPTS)
   # optimization options
   OPTIMISE_OPTS = -Os -fomit-frame-pointer
   # dependencies must be up to date
   CHECK_DEPS = yes

  else

   # Other goals do not require up to date dependencies.
   CHECK_DEPS = no

  endif
 endif
endif

# preprocessor options
CPPOPTS = $(INC_PATH)

# compiler options
CXXOPTS = $(GOAL_OPTS) $(COMPILE_OPTS) $(WARN_OPTS) $(OPTIMISE_OPTS)

# linker options
LDOPTS = $(GOAL_OPTS) $(LNK_LIBS)

# source files in this project
sources := $(wildcard $(srcdir)/*.$(SOURCE_SUFFIX))

# object files in this project
objs := $(notdir $(sources))
objs := $(addprefix $(builddir)/, $(objs))
objs := $(objs:.$(SOURCE_SUFFIX)=.o)

# executable with full path
exe = $(builddir)/$(EXE)

# This makefile creates and includes makefiles containing actual dependencies.
# For every source file a dependencies makefile is created and included.
# The deps variable contains the list of all dependencies makefiles.
deps_suffix = d
deps := $(objs:.o=.$(deps_suffix))

# To detect goal changes (for instance from GOAL_DEBUG to GOAL_EXE)
# between invocations, this makefile creates an empty file (the goal flag
# file) which suffix is the goal name.
goal_flag_file_prefix = $(builddir)/Last_make_goal_was_
goal_flag_file = $(goal_flag_file_prefix)$(MAKECMDGOALS)

###############################################################################
# TARGETS
###############################################################################

# Delete the target file of a rule if the command used to update it failed.
# Do that because the newly generated target file may be corrupted but appear
# up to date.
.DELETE_ON_ERROR:

# Clear default suffix list to disable all implicit rules.
.SUFFIXES:

# usage message for this makefile
.PHONY:	usage
usage:
164 165 166 167 168 169 170 171
	@echo "GOAL      EFFECT"
	@echo "----      ------"
	@echo "usage     print this message"
	@echo "list      list the source files"
	@echo "$(GOAL_EXE)       build the executable"
	@echo "$(GOAL_DEBUG)     build the executable with debug options"
	@echo "$(GOAL_PROF)      build the executable with profiling options"
	@echo "clean     remove all built files"
172 173
	@echo "install   install executable, manual, and high scores files"
	@echo "uninstall remove executable and manual files"
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260

# If source files exist then build the EXE file.
.PHONY:	$(GOAL_EXE)
ifneq "$(strip $(sources))" ""
$(GOAL_EXE):	$(exe)
else
$(GOAL_EXE):
	@echo "No source file found."
endif

# GOAL_DEBUG and GOAL_PROF targets use the same rules than GOAL_EXE.
.PHONY:	$(GOAL_DEBUG)
$(GOAL_DEBUG):	$(GOAL_EXE)

.PHONY:	$(GOAL_PROF)
$(GOAL_PROF):	$(GOAL_EXE)

###############################################################################
# BUILDING
# Note: CPPFLAGS, CXXFLAGS or LDFLAGS are not used but may be specified by the
# user at make invocation.
###############################################################################

# linking
$(exe):	$(objs)
	$(CXX) $^ -o $@ $(LDOPTS) $(LDFLAGS)

# explicit definition of the implicit rule used to compile source files
$(builddir)/%.o:	$(srcdir)/%.$(SOURCE_SUFFIX)
	$(CXX) -c $< $(CPPOPTS) $(CXXOPTS) $(CPPFLAGS) $(CXXFLAGS) -o $@

# Rule to build our included dependencies makefiles.
# This rule is used by GNU Make because it automatically tries to (re)build
# obsolete or non-existent included makefiles.
# These files are created with one line of the form:
# 1.o 1.d: $(goal_flag_file) 1.cc 1.h 2.h 3.h g.h
# The implicit rule previously defined will be used for compilation.
# Note that the dependencies can be goal specific.
# The goal_flag_file is determined at run time because it must be the current
# goal and not the goal in use when the dependencies makefile was created.
$(builddir)/%.$(deps_suffix):	$(srcdir)/%.$(SOURCE_SUFFIX) $(goal_flag_file)
	$(SHELL) -ec '$(CXX) -MM $(CPPOPTS) $(CPPFLAGS) $< |\
	sed '\''s@\($*\)\.o[ :]*@$(builddir)/\1.o $@: $$(goal_flag_file) @g'\'' > $@;\
	[ -s $@ ] || rm -f $@'

# If dependencies have to be up to date then include dependencies makefiles.
ifeq "$(CHECK_DEPS)" "yes"
 ifneq "$(strip $(sources))" ""
  include $(deps)
 endif
endif

# Rule to produce the goal flag file.
# If the goal has changed then we must rebuild on a clean state because
# pre-processor DEFINE's may have changed.
$(goal_flag_file):
	rm -f $(exe) $(goal_flag_file_prefix)* $(objs) $(deps)
	touch $@

###############################################################################
# NON-BUILD TARGETS
###############################################################################

# List the source files
.PHONY:	list
list:
	@echo $(sources) | tr [:space:] \\n

# Remove all files that are normally created by building the program.
.PHONY:	clean
clean:
	rm -f $(exe) $(goal_flag_file_prefix)* $(objs) $(deps)

###############################################################################
# INSTALLATION TARGETS
###############################################################################

# Installation procedure
# Customized for XGalaga++
install:
	cp $(EXE) $(bindir)
	if [ -n "$(MANUAL)" ]; then cp $(MANUAL) $(mandir); fi
	if [ -n "$(EXE_GROUP)" ]; then chgrp $(EXE_GROUP) $(bindir)/$(EXE); fi
	chmod g+s $(bindir)/$(EXE)
	touch $(HIGH_SCORES_FILE)
	if [ -n "$(EXE_GROUP)" ]; then chgrp $(EXE_GROUP) $(HIGH_SCORES_FILE); fi
	chmod 664 $(HIGH_SCORES_FILE)
261 262 263 264 265

.PHONY:	uninstall
uninstall:
	rm $(bindir)/$(EXE)
	rm $(mandir)/$(MANUAL)