-
Notifications
You must be signed in to change notification settings - Fork 20
/
Makefile
365 lines (293 loc) · 12.5 KB
/
Makefile
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
33
34
35
36
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
164
165
166
167
168
169
170
171
172
173
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
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
##############################################################################
# MCGPU Makefile
# Version 2.0
#
# This Makefile depends on GNU make.
#
########################
# Makefile Target List #
########################
#
# make [all] : Compiles all source files and builds the main application
# in release mode.
# make tests : Compiles all source files and unittesting source files and
# builds a release versions of the testing application.
# make dirtree : Creates all of the directories needed by the makefile to
# store the generated output files.
# make clean : Deletes the object and bin directories from the project
# folder, removing all generated files.
#
##############################
# Makefile Defined Variables #
##############################
#
# BUILD=debug : Builds the program in debug mode
# BUILD=profile : Builds the program in profiling mode
# BUILD=release : Builds the program in release mode
#
# PRECISION=single : All floating point numbers use single-precision
# PRECISION=double : All floating point numbers use double-precision
#
# SHELL=path/to/file : The relative path to the shell executable program on
# the current machine. This shell program will allow the
# makefile to execute system commands
#
##############################################################################
#########################
# Environment Variables #
#########################
# The location of the shell script program that will execute scripts from
# the makefile. This is specified as per GNU Makefile conventions.
SHELL = /bin/sh
#############################
# Project Structure Details #
#############################
# The relative path to the directory containing the source files
SourceDir := src
# The relative path to the directory containing the unit tests
TestDir := test
# The relative path to the object directory
ObjDir := obj
# The relative path to the bin directory
BinDir := bin
# The path to the output directory where the built executables will be stored
AppDir := $(BinDir)
# The path to the output directory where the compiled object files will be
# built, as well as the dependency information files
BuildDir := $(ObjDir)
# Defines the modules that exist in the source directory that should be
# included by the compiler. All files within these directories that are
# valid file types for the Makefile to handle will automatically be
# compiled into object files in the build directory. Make sure to add
# any new modules to this list, or else they will not be compiled.
# NOTE: If a file is no longer being used make sure to remove it from
# the module directory, else it will be included in the build.
Modules := Applications \
Metropolis \
Metropolis/Utilities \
Metropolis/SerialSim \
########################
# Program Output Names #
########################
# The name of the main program generated by the makefile
AppName := metrosim
# The name of the unit testing program generated by the makefile
UnitTestName := metrotest
##############################
# Compiler Settings #
##############################
# Defines the compiler used to compile and link the source files.
CC := pgc++
# Defines compiler-specific flags
# Some of the GNU C++ library headers included by the Google Test
# infrastructure use C++11 features (notably, variadic templates)
ifeq ($(CC),pgc++)
CFLAGS := --c++11
else
CFLAGS := -std=c++11
endif
# Defines the types of files that the Makefile knows how to compile
# and link. Specify the filetype by using a modulus (percent sign),
# followed by a dot and the file extension (e.g. %.java, %.txt).
FileTypes := %.cpp
# Relative search paths for Include Files. We include the root folder, the
# source folder, and the testing folder.
IncPaths := . $(SourceDir) $(TestDir)
# Compiler specific flags for the C++ compiler when generating .o files
# and when generating .d files for dependency information
ifeq ($(CC),pgc++)
CompileFlags := -c -acc -ta=nvidia -Minfo=accel
else
CompileFlags := -c
endif
# Flags for linking metrosim with the PGI compiler.
ifeq ($(CC),pgc++)
LinkFlags := -acc -ta=nvidia -Minfo=accel
else
LinkFlags := -lgomp
endif
# The debug compiler flags add debugging symbols to the executable
# This originally contained -Minfo=ccff
DebugFlags := -g
# The profile compiler flags add profiling hooks (which produce gmon.out)
# as well as debugging symbols, but optimizations are still enabled
ProfileFlags := -g -O3 -mp -pg
# The release build compiler flags that add optimization flags and remove
# all symbol and relocation table information from the executable.
ReleaseFlags := -O3 -s
ifeq ($(CC),pgc++)
ReleaseFlags += -mp
endif
#############################
# Automated Testing Details #
#############################
# The relative path to the testing module containing the unit test source.
UnitTestDir := $(TestDir)/unittests
# The relative path to the Google Test module that contains the source
# code and libraries for the Google Test framework.
GTestDir := gtest
# All Google Test headers. Usually you shouldn't change this
# definition.
GTestHeaders = $(GTestDir)/include/gtest/*.h \
$(GTestDir)/include/gtest/internal/*.h
# Flags passed to the preprocessor.
# Set Google Test's header directory as a system directory, such that
# the compiler doesn't generate warnings in Google Test headers.
GTestFlags := -I$(GTestDir)/include
ifeq ($(CC),g++)
GTestFlags += -lpthread
endif
#GTestFlags += -pthread #-Wall -Wextra
# Builds gtest.a and gtest_main.a.
# Usually you shouldn't tweak such internal variables, indicated by a
# trailing _.
GTEST_SRCS_ = $(GTestDir)/src/*.cc $(GTestDir)/src/*.h $(GTestHeaders)
###########################
# Application Definitions #
###########################
# The base define list to pass to the compiled and linked executable.
Definitions := APP_NAME=\"$(AppName)\"
# Check for the BUILD definition: debug, profile, or release. If this is is not
# set by the user, then the build will default to a release build. If the user
# specifies an option other than 'debug', 'profile', or 'release', then the
# build will default to release build.
ifeq ($(BUILD),debug)
# "Debug" build - set compiling and linking flags
CompileFlags += $(DebugFlags)
LinkFlags += $(DebugFlags)
BuildDir := $(BuildDir)/debug
Definitions += DEBUG
else
ifeq ($(BUILD),profile)
# "Profile" build - set compiling and linking flags
CompileFlags += $(ProfileFlags)
LinkFlags += $(ProfileFlags)
BuildDir := $(BuildDir)/profile
Definitions += PROFILE
else
# "Release" build - set compiling and linking flags
CompileFlags += $(ReleaseFlags)
LinkFlags += $(ReleaseFlags)
BuildDir := $(BuildDir)/release
Definitions += RELEASE
endif
endif
# Check for the PRECISION definition being set to single or double. If this
# define is not set by the user, then the build will default to double
# precision. If the user specifies an option other than 'single' or 'double'
# then the build will default to double precision.
ifeq ($(PRECISION),single)
Definitions += SINGLE_PRECISION
else
Definitions += DOUBLE_PRECISION
endif
######################
# Internal Variables #
######################
# The main application file that contains the entry point for the application
ProgramMain := $(BuildDir)/$(SourceDir)/Program.o
# Derives the compiler flags for included search paths
Includes := $(addprefix -I, $(IncPaths))
# Derives the compiler flags for defined variables for the application
Defines := $(addprefix -D, $(Definitions))
# Derives the paths to each of the source modules
SourceModules := $(addprefix $(SourceDir)/,$(Modules))
# Creates a list of folders inside the object output directory that need
# to be created for the compiled files.
ObjFolders := $(addprefix $(BuildDir)/,$(SourceModules))
ObjFolders += $(BuildDir)/$(UnitTestDir)
# Searches through the specified Modules list for all of the valid
# files that it can find and compile. Once all of the files are
# found, they are appended with an .o and prefixed with the object
# directory path. This allows the compiled object files to be routed
# to the proper output directory.
Sources := $(filter $(FileTypes),$(wildcard $(addsuffix /*,$(SourceModules))))
Objects := $(patsubst %,$(BuildDir)/%.o,$(basename $(Sources)))
# The unit testing objects are all gathered seperately because they are
# included all at once from the testing directory and are compiled into the
# output program alongside the source objects.
UnitTestingSources := $(filter %.cpp,$(wildcard $(UnitTestDir)/*))
UnitTestingObjects := $(patsubst %,$(BuildDir)/%.o,\
$(basename $(UnitTestingSources)))
##############################
# Dependency Graph Functions #
##############################
# The function to create the formated dependency graph file after having the
# generated compiler file (*.d) piped in from the compiler.
format_dep = sed -n "H;$$ {g;s@.*:\(.*\)@$(basename $@).o $@: \$$\(wildcard\1\)@;p}" > $@
# The command that will generate the dependency file (*.d) output for a given
# C++ file using the C++ compiler
create_dep_cpp = $(CC) $(CFLAGS) $(Includes) $(Defines) -MM $<
# The command that will generate the dependency file (*.d) output for a given
# unit testing file. These files are special because they use specific flags
# that link the testing framework.
create_dep_unittest = $(CC) $(CFLAGS) $(GTestFlags) $(Includes) $(Defines) -MM $<
##############################
# Makefile Rules and Targets #
##############################
# Specifies that these make targets are not actual files and therefore will
# not break if a similar named file exists in the directory.
.PHONY : all tests $(AppName) $(UnitTestName) dirtree clean
# The list of build targets that the user can specify
all : $(AppName)
tests : $(AppName) $(UnitTestName)
$(AppName) : $(Objects) $(ProgramMain) | dirtree
$(CC) $^ $(CFLAGS) $(Includes) $(Defines) -o $(AppDir)/$@ $(LinkFlags)
$(UnitTestName) : $(Objects) $(UnitTestingObjects) $(ObjDir)/gtest_main.a | dirtree
$(CC) $^ $(CFLAGS) $(GTestFlags) $(Includes) $(Defines) -o $(AppDir)/$@ $(LinkFlags)
dirtree :
@mkdir -p $(ObjFolders) $(BinDir) $(ObjDir) $(AppDir) $(BuildDir)
clean :
rm -rf $(ObjDir) $(BinDir)
################################
# Object and Source File Rules #
################################
# For simplicity and to avoid depending on Google Test's
# implementation details, the dependencies specified below are
# conservative and not optimized. This is fine as Google Test
# compiles fast and for ordinary users its source rarely changes.
$(ObjDir)/gtest-all.o : $(GTEST_SRCS_) | dirtree
$(CC) $(CFLAGS) $(GTestFlags) -I$(GTestDir) -c \
$(GTestDir)/src/gtest-all.cc -o $@
$(ObjDir)/gtest_main.o : $(GTEST_SRCS_) | dirtree
$(CC) $(CFLAGS) $(GTestFlags) -I$(GTestDir) -c \
$(GTestDir)/src/gtest_main.cc -o $@
$(ObjDir)/gtest.a : $(ObjDir)/gtest-all.o | dirtree
$(AR) $(ARFLAGS) $@ $^
$(ObjDir)/gtest_main.a : $(ObjDir)/gtest-all.o $(ObjDir)/gtest_main.o | dirtree
$(AR) $(ARFLAGS) $@ $^
# Here are the Rules that determine how to compile a C++ source
# file into an object file. Note that we have specified a special rule for
# unit testing object files, as they use a special set of compiler flags
# in order to meet the Google Test framework requirements.
$(BuildDir)/$(UnitTestDir)/%.o : $(UnitTestDir)/%.cpp $(GTestHeaders) | dirtree
$(CC) $(CFLAGS) $(CompileFlags) $(GTestFlags) $(Defines) $(Includes) $< -o $@
$(BuildDir)/%.o : %.cpp | dirtree
$(CC) $(CFLAGS) $(CompileFlags) $(Includes) $(Defines) $< -o $@
##########################
# Dependency Build Rules #
##########################
# These rules specify how to generate the dependency graph information
# for each of the object files used in linking the final executables.
# We have a special rule for unit testing because it contains special
# compiler flags.
$(BuildDir)/$(UnitTestDir)/%.dep : $(UnitTestDir)/%.cpp | dirtree
$(SHELL) -ec '$(create_dep_unittest) | $(format_dep)'
$(BuildDir)/%.dep : %.cpp | dirtree
$(SHELL) -ec '$(create_dep_cpp) | $(format_dep)'
######################
# Dependency Include #
######################
# This conditional statement will attempt to include all of the dependency
# files located in the object directory. If the files exist, then their
# dependency information is loaded, and each source file checks to see if
# it needs to be recompiled. The if statements are used to make sure that
# the dependency info isn't rebuilt when the object directory is being
# cleaned or when some other target is selected that doesn't generate files.
ifneq ($(MAKECMDGOALS),dirtree)
ifneq ($(MAKECMDGOALS),clean)
-include $(Objects:.o=.dep)
-include $(ProgramMain:.o=.dep)
-include $(UnitTestingObjects:.o=.dep)
endif
endif