Makefile

Fri, 25 Sep 2009 10:51:24 +0100

author
Philip Pemberton <philpem@philpem.me.uk>
date
Fri, 25 Sep 2009 10:51:24 +0100
changeset 22
0e75b61c7aa4
parent 9
ebce4a7615e9
permissions
-rw-r--r--

test app now a little more interesting -- prints component box labels

philpem@0 1 # Phil's multiplatform makefile template
philpem@0 2 # With auto-incrementing build number and automatic version.h generation
philpem@0 3 # Version 1.4, 2009-01-27
philpem@0 4 #
philpem@0 5 # The latest version of this Makefile can be found at http://www.philpem.me.uk/
philpem@0 6 #
philpem@0 7 #
philpem@0 8 # Copyright (c) 2009 Philip Pemberton <code@philpem.me.uk>
philpem@0 9 #
philpem@0 10 # Permission is hereby granted, free of charge, to any person obtaining a copy
philpem@0 11 # of this software and associated documentation files (the "Software"), to deal
philpem@0 12 # in the Software without restriction, including without limitation the rights
philpem@0 13 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
philpem@0 14 # copies of the Software, and to permit persons to whom the Software is
philpem@0 15 # furnished to do so, subject to the following conditions:
philpem@0 16 #
philpem@0 17 # The above copyright notice and this permission notice shall be included in
philpem@0 18 # all copies or substantial portions of the Software.
philpem@0 19 #
philpem@0 20 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
philpem@0 21 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
philpem@0 22 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
philpem@0 23 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
philpem@0 24 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
philpem@0 25 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
philpem@0 26 # THE SOFTWARE.
philpem@0 27 #
philpem@0 28 #
philpem@0 29 # Instructions for use:
philpem@0 30 # Run 'make init' to create the required directories
philpem@0 31 # Add your source files to the 'SOURCES' list, and change the TARGET filename
philpem@0 32 # Set the desired build type and platform in the BUILD_TYPE and PLATFORM
philpem@0 33 # variables respectively
philpem@0 34 # Set your project type (C only, or C++) in the SRC_TYPE variable
philpem@0 35 # Add any libraries you need to link against to the 'LIB' list
philpem@0 36 # Run 'make'
philpem@0 37 #
philpem@0 38 # Object files are created in the 'obj' subdirectory, from source code in the
philpem@0 39 # 'src' directory. Dependency files are created in the 'dep' directory from
philpem@0 40 # the same source code the object files are created from.
philpem@0 41 #
philpem@0 42 # Supported targets are:
philpem@0 43 # all Build everything.
philpem@0 44 # update-revision Increment the build number without building anything.
philpem@0 45 # clean-versioninfo Delete src/version.h (will be rebuilt on the next
philpem@0 46 # 'make all').
philpem@0 47 # init Initialise the build system for a new project.
philpem@0 48 # WARNING: overwrites .buildnum and src/version.h.in!
philpem@0 49 # cleandep Delete all dependency files.
philpem@0 50 # clean Delete all dependency, intermediate and target files.
philpem@0 51 # tidy Delete all dependency and intermediate files, leaving
philpem@0 52 # the target file intact.
philpem@0 53 #
philpem@0 54 # If you want to reset the build number to zero, delete '.buildnum'. This
philpem@0 55 # should be done whenever the major or minor version changes. Excluding
philpem@0 56 # .buildnum from version control may also be a good idea, depending on how
philpem@0 57 # you want your build numbers to work.
philpem@0 58 #
philpem@0 59 # The BUILD_TYPE variable contains the current build type. There are two
philpem@0 60 # supported build types:
philpem@0 61 # debug Debug mode - object files are compiled with debug information
philpem@0 62 # and the target is left unstripped.
philpem@0 63 # release Release mode - object files are not compiled with debug info,
philpem@0 64 # and the target is fed through strip to remove redundant
philpem@0 65 # data.
philpem@0 66 #
philpem@0 67 # The PLATFORM variable contains the current target platform. There are two
philpem@0 68 # supported platforms:
philpem@0 69 # linux GNU/Linux with GNU Compiler Collection
philpem@0 70 # win32 Windows 32-bit with MinGW
philpem@0 71 #
philpem@0 72 # The EXTSRC variable is used to specify other files to build. It is typically
philpem@0 73 # used to specify platform or build-type specific source files, e.g.
philpem@0 74 #
philpem@0 75 # ifeq ($(BUILD_TYPE),debug-memwatch)
philpem@0 76 # CFLAGS += -g -ggdb
philpem@0 77 # CPPFLAGS += -DMEMWATCH
philpem@0 78 # INCPATH += ./memwatch
philpem@0 79 # EXTSRC += memwatch/memwatch.c
philpem@0 80 # endif
philpem@0 81 #
philpem@0 82 # (example taken from one of my projects that allowed the use of Memwatch to
philpem@0 83 # track down memory allocation/deallocation bugs)
philpem@0 84 #
philpem@0 85
philpem@0 86 ####
philpem@0 87 # Build configuration
philpem@0 88 ####
philpem@0 89
philpem@0 90 # version information -- major.minor.extra
philpem@0 91 # note that VER_EXTRA can be overridden on the command line, e.g.:
philpem@0 92 # make VER_EXTRA=12345 all
philpem@0 93 VER_MAJOR = 0
philpem@0 94 VER_MINOR = 0
philpem@0 95 VER_EXTRA ?=
philpem@0 96
philpem@0 97 # build platform: win32 or linux
philpem@0 98 PLATFORM ?= linux
philpem@0 99 # build type: release or debug
philpem@0 100 BUILD_TYPE ?= debug
philpem@0 101
philpem@0 102 # target executable
philpem@0 103 TARGET = ptouch
philpem@0 104
philpem@0 105 # source files that produce object files
philpem@7 106 SRC = main.c hexdump.c ptouch.c
philpem@0 107
philpem@0 108 # source type - either "c" or "cpp" (C or C++)
philpem@0 109 SRC_TYPE = c
philpem@0 110
philpem@0 111 # additional object files that don't necessarily include source
philpem@0 112 EXT_OBJ =
philpem@0 113 # libraries to link in -- these will be specified as "-l" parameters, the -l
philpem@0 114 # is prepended automatically
philpem@0 115 #LIB = jpeg tiff png z
philpem@9 116 LIB = gd
philpem@0 117 # library paths -- where to search for the above libraries
philpem@0 118 LIBPATH =
philpem@0 119 # include paths -- where to search for #include files (in addition to the
philpem@0 120 # standard paths
philpem@0 121 INCPATH =
philpem@0 122 # garbage files that should be deleted on a 'make clean' or 'make tidy'
philpem@0 123 GARBAGE =
philpem@0 124
philpem@0 125 # extra dependencies - files that we don't necessarily know how to build, but
philpem@0 126 # that are required for building the application; e.g. object files or
philpem@0 127 # libraries in sub or parent directories
philpem@0 128 EXTDEP =
philpem@0 129
philpem@0 130 ####
philpem@0 131 # Win32 target-specific settings
philpem@0 132 ####
philpem@0 133 ifeq ($(strip $(PLATFORM)),win32)
philpem@0 134 # windows executables have a .exe suffix
philpem@0 135 TARGET := $(addsuffix .exe,$(TARGET))
philpem@0 136 # console mode application
philpem@0 137 EXT_CFLAGS = -mconsole
philpem@0 138 # additional libraries required by CImg on win32
philpem@0 139 LIB += gdi32
philpem@0 140 endif
philpem@0 141
philpem@0 142 ####
philpem@0 143 # Linux target-specific settings
philpem@0 144 ####
philpem@0 145 ifeq ($(strip $(PLATFORM)),linux)
philpem@0 146 # additional libraries required by CImg on linux
philpem@0 147 LIB += m pthread X11
philpem@0 148 endif
philpem@0 149
philpem@0 150
philpem@0 151 ####
philpem@0 152 # Tool setup
philpem@0 153 ####
philpem@0 154 MAKE = make
philpem@0 155 CC = gcc
philpem@0 156 CXX = g++
philpem@0 157 CFLAGS = -Wall -pedantic -std=gnu99 $(EXT_CFLAGS)
philpem@0 158 CXXFLAGS= -Wall -pedantic $(EXT_CXXFLAGS)
philpem@0 159 LDFLAGS = $(EXT_LDFLAGS)
philpem@0 160 RM = rm
philpem@0 161 STRIP = strip
philpem@0 162
philpem@0 163 ###############################################################################
philpem@0 164 # You should not need to touch anything below here, unless you're adding a new
philpem@0 165 # platform or build type (or changing the version string format)
philpem@0 166 ###############################################################################
philpem@0 167
philpem@0 168 ####
philpem@0 169 # A quick sanity check on the platform type
philpem@0 170 ####
philpem@0 171 ifneq ($(PLATFORM),linux)
philpem@0 172 ifneq ($(PLATFORM),win32)
philpem@0 173 $(error Platform '$(PLATFORM)' not supported. Supported platforms are: linux, win32)
philpem@0 174 endif
philpem@0 175 endif
philpem@0 176
philpem@0 177 ####
philpem@0 178 # Version info generation
philpem@0 179 ####
philpem@0 180 # get the current build number
philpem@0 181 VER_BUILDNUM = $(shell cat .buildnum)
philpem@0 182
philpem@0 183 # there are two ways to get the SVN rev - use svnversion, or use svn info
philpem@0 184 # then pipe through awk. which one you use is up to you.
philpem@0 185 VER_SVNREV = $(shell LANG=C svn info 2>/dev/null || echo 'Revision: 0' | awk '/^Revision:/ { print$$2 }' )
philpem@0 186 #VER_SVNREV = $(shell svnversion .)
philpem@0 187
philpem@0 188 # if the version string is "exported", then the CSD was not checked out of SVN
philpem@0 189 # note that if the CSD is not an SVN checkout, then @@svnrev@@ will be set to
philpem@0 190 # zero.
philpem@0 191 ifeq ($(VER_SVNREV),exported)
philpem@0 192 VER_SVNREV = 0
philpem@0 193 endif
philpem@0 194
philpem@0 195 # start creating the revision string
philpem@0 196 VER_FULLSTR = $(VER_MAJOR).$(VER_MINOR).$(VER_BUILDNUM)$(VER_EXTRA)
philpem@0 197
philpem@0 198 # if this is an SVN release, include the SVN revision in the version string
philpem@0 199 ifneq ($(VER_SVNREV),0)
philpem@0 200 VER_FULLSTR += (svn $(VER_SVNREV))
philpem@0 201 endif
philpem@0 202
philpem@0 203
philpem@0 204 ####
philpem@0 205 # Build-type specific configuration
philpem@0 206 ####
philpem@0 207 ifeq ($(BUILD_TYPE),debug)
philpem@0 208 CFLAGS += -g -ggdb
philpem@0 209 CXXFLAGS += -g -ggdb
philpem@0 210 else
philpem@0 211 ifeq ($(BUILD_TYPE),release)
philpem@0 212 CFLAGS += -O2
philpem@0 213 CXXFLAGS += -O2
philpem@0 214 else
philpem@0 215 $(error Unsupported build type: '$(BUILD_TYPE)')
philpem@0 216 endif
philpem@0 217 endif
philpem@0 218
philpem@0 219 ####
philpem@0 220 # rules
philpem@0 221 ####
philpem@0 222
philpem@0 223 # object files
philpem@0 224 OBJ = $(addprefix obj/, $(addsuffix .o, $(basename $(SRC))) $(EXT_OBJ)) $(addsuffix .o, $(basename $(EXTSRC)))
philpem@0 225
philpem@0 226 # dependency files
philpem@0 227 DEPFILES = $(addprefix dep/, $(addsuffix .d, $(basename $(SRC))) $(EXT_OBJ)) $(addsuffix .d, $(basename $(EXTSRC)))
philpem@0 228
philpem@0 229 # path commands
philpem@0 230 LIBLNK = $(addprefix -l, $(LIB))
philpem@0 231 LIBPTH = $(addprefix -L, $(LIBPATH))
philpem@0 232 INCPTH = $(addprefix -I, $(INCPATH))
philpem@0 233
philpem@0 234 CPPFLAGS += $(INCPTH)
philpem@0 235
philpem@0 236 ####
philpem@0 237 # Make sure there is at least one object file to be linked in
philpem@0 238 ####
philpem@0 239 ifeq ($(strip $(OBJ)),)
philpem@0 240 $(error Unable to build: no object or source files specified in Makefile)
philpem@0 241 endif
philpem@0 242
philpem@0 243 ####
philpem@0 244 # targets
philpem@0 245 ####
philpem@0 246 .PHONY: default all update-revision versionheader clean-versioninfo init cleandep clean tidy
philpem@0 247
philpem@0 248 all: update-revision
philpem@0 249 @$(MAKE) versionheader
philpem@0 250 $(MAKE) $(TARGET)
philpem@0 251
philpem@0 252 # increment the current build number
philpem@0 253 NEWBUILD=$(shell expr $(VER_BUILDNUM) + 1)
philpem@0 254 update-revision:
philpem@0 255 @echo $(NEWBUILD) > .buildnum
philpem@0 256
philpem@0 257 versionheader:
philpem@0 258 @sed -e 's/@@date@@/$(shell LC_ALL=C date)/g' \
philpem@0 259 -e 's/@@time@@/$(shell LC_ALL=C date +%T)/g' \
philpem@0 260 -e 's/@@whoami@@/$(shell whoami)/g' \
philpem@0 261 -e 's/@@hostname@@/$(shell hostname)/g' \
philpem@0 262 -e 's|@@compiler@@|$(shell $(CC) $(CFLAGS) -v 2>&1 | tail -n 1 | sed -e "s;|;/;")|g' \
philpem@0 263 -e 's/@@majorver@@/$(VER_MAJOR)/g' \
philpem@0 264 -e 's/@@minorver@@/$(VER_MINOR)/g' \
philpem@0 265 -e 's/@@extraver@@/$(subst \",,$(VER_EXTRA))/g' \
philpem@0 266 -e 's/@@buildnum@@/$(VER_BUILDNUM)/g' \
philpem@0 267 -e 's/@@buildtype@@/$(BUILD_TYPE)/g' \
philpem@0 268 -e 's/@@svnrev@@/$(VER_SVNREV)/g' \
philpem@0 269 -e 's/@@fullverstr@@/$(VER_FULLSTR)/g' \
philpem@0 270 -e 's/@@cflags@@/$(CFLAGS)/g' \
philpem@0 271 < src/version.h.in > src/version.h
philpem@0 272
philpem@0 273 # version.h creation stuff based on code from the Xen makefile
philpem@0 274 clean-versioninfo:
philpem@0 275 @if [ ! -r src/version.h -o -O src/version.h ]; then \
philpem@0 276 rm -f src/version.h; \
philpem@0 277 fi
philpem@0 278 @echo 0 > .buildnum
philpem@0 279
philpem@0 280 # initialise the build system for a new project
philpem@0 281 init:
philpem@0 282 @mkdir -p src dep obj
philpem@0 283 @echo 0 > .buildnum
philpem@0 284 @echo '#define VER_COMPILE_DATE "@@date@@"' > src/version.h.in
philpem@0 285 @echo '#define VER_COMPILE_TIME "@@time@@"' >> src/version.h.in
philpem@0 286 @echo '#define VER_COMPILE_BY "@@whoami@@"' >> src/version.h.in
philpem@0 287 @echo '#define VER_COMPILE_HOST "@@hostname@@"' >> src/version.h.in
philpem@0 288 @echo '#define VER_COMPILER "@@compiler@@"' >> src/version.h.in
philpem@0 289 @echo '#define VER_BUILD_TYPE "@@buildtype@@"' >> src/version.h.in
philpem@0 290 @echo '#define VER_CFLAGS "@@cflags@@"' >> src/version.h.in
philpem@0 291 @echo '' >> src/version.h.in
philpem@0 292 @echo '#define VER_MAJOR @@majorver@@' >> src/version.h.in
philpem@0 293 @echo '#define VER_MINOR @@minorver@@' >> src/version.h.in
philpem@0 294 @echo '#define VER_BUILDNUM @@buildnum@@' >> src/version.h.in
philpem@0 295 @echo '#define VER_EXTRA "@@extraver@@"' >> src/version.h.in
philpem@0 296 @echo '#define VER_SVNREV @@svnrev@@' >> src/version.h.in
philpem@0 297 @echo '' >> src/version.h.in
philpem@0 298 @echo '#define VER_FULLSTR "@@fullverstr@@"' >> src/version.h.in
philpem@0 299 @echo '' >> src/version.h.in
philpem@0 300 @echo Build system initialised
philpem@0 301
philpem@0 302 # remove the dependency files
philpem@0 303 cleandep:
philpem@0 304 -rm $(DEPFILES)
philpem@0 305
philpem@0 306 # remove the dependency files and any target or intermediate build files
philpem@0 307 clean: cleandep clean-versioninfo
philpem@0 308 -rm $(OBJ) $(TARGET) $(GARBAGE)
philpem@0 309
philpem@0 310 # remove any dependency or intermediate build files
philpem@0 311 tidy: cleandep clean-versioninfo
philpem@0 312 -rm $(OBJ) $(GARBAGE)
philpem@0 313
philpem@0 314 #################################
philpem@0 315
philpem@0 316 $(TARGET): $(OBJ) $(EXTDEP)
philpem@0 317 ifeq ($(SRC_TYPE),c)
philpem@0 318 $(CC) $(CXXFLAGS) $(LDFLAGS) $(OBJ) $(LIBPTH) $(LIBLNK) -o $@
philpem@0 319 else
philpem@0 320 $(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJ) $(LIBPTH) $(LIBLNK) -o $@
philpem@0 321 endif
philpem@0 322 ifeq ($(BUILD_TYPE),release)
philpem@0 323 $(STRIP) $(TARGET)
philpem@0 324 endif
philpem@0 325
philpem@0 326 ###
philpem@0 327 # extra rules
philpem@0 328 # example:
philpem@0 329 #src/parser.c: src/parser.h
philpem@0 330
philpem@0 331 ####
philpem@0 332 # make object files from C source files
philpem@0 333 obj/%.o: src/%.c
philpem@0 334 $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@
philpem@0 335
philpem@0 336 ##
philpem@0 337 # make object files from C++ source files
philpem@0 338 obj/%.o: src/%.cc
philpem@0 339 $(CXX) -c $(CXXFLAGS) $(CPPFLAGS) $< -o $@
philpem@0 340
philpem@0 341 obj/%.o: src/%.cpp
philpem@0 342 $(CXX) -c $(CXXFLAGS) $(CPPFLAGS) $< -o $@
philpem@0 343
philpem@0 344 ###
philpem@0 345 # make C files from yacc/bison source
philpem@0 346 src/%.h src/%.c: src/%.y
philpem@0 347 $(YACC) $(YFLAGS) -d $<
philpem@0 348 mv -f y.tab.c $*.c
philpem@0 349 mv -f y.tab.h $*.h
philpem@0 350
philpem@0 351 ###
philpem@0 352 # make C files from lex/flex source
philpem@0 353 src/%.c: src/%.l
philpem@0 354 $(LEX) $(LFLAGS) -o$@ $<
philpem@0 355
philpem@0 356 ###
philpem@0 357 # make dependencies for our source files
philpem@0 358 dep/%.d: src/%.c
philpem@0 359 $(CC) -MM $(CPPFLAGS) $< > $@.$$$$; \
philpem@0 360 sed 's,\($*\)\.o[ :]*,obj/\1.o $@ : ,g' < $@.$$$$ > $@; \
philpem@0 361 rm -f $@.$$$$
philpem@0 362
philpem@0 363 dep/%.d: src/%.cpp
philpem@0 364 $(CXX) -MM $(CPPFLAGS) $< > $@.$$$$; \
philpem@0 365 sed 's,\($*\)\.o[ :]*,obj/\1.o $@ : ,g' < $@.$$$$ > $@; \
philpem@0 366 rm -f $@.$$$$
philpem@0 367
philpem@0 368 dep/%.d: src/%.cc
philpem@0 369 $(CXX) -MM $(CPPFLAGS) $< > $@.$$$$; \
philpem@0 370 sed 's,\($*\)\.o[ :]*,obj/\1.o $@ : ,g' < $@.$$$$ > $@; \
philpem@0 371 rm -f $@.$$$$
philpem@0 372
philpem@0 373 ####
philpem@0 374 # pull in the dependency files, but only for 'make $(TARGET)'
philpem@0 375 ####
philpem@0 376
philpem@0 377 ifeq ($(MAKECMDGOALS),$(TARGET))
philpem@0 378 -include $(DEPFILES)
philpem@0 379 endif