forked from orlandoacevedo/MCGPU
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Makefile
473 lines (384 loc) · 17.1 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
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
##############################################################################
# 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=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
#
# LOCAL_INSTALL=1 : Sets the default directory for the CUDA installation
# path to '/usr/local/cuda'
# LOCAL_INSTALL=0 : Sets the default directory for the CUDA installation
# path to 'opt/asn/apps/cuda_5.5'. This is the directory
# used by the ASC machines that we test on.
#
# MAC=1 : Sets up compilation for Mac OS X environment. Sets the default directory for the CUDA_GCC installation
# path to ‘/opt/local/bin’
# MAC=0 : Sets up compilation for Linux. This is set by default.
#
# CUDA_PATH=path/to/dir : The relative path to the cuda install directory
# on the current machine.
#
# CUDA_INCLUDE_PATH=path/to/dir : The relative path to the cuda header files
# installed on the current machine
#
# CUDA_BIN_PATH=path/to/dir : The relative path to the cuda bin directory
# installed on the current machine
#
# CUDA_LIB_PATH=path/to/dir : The relative path to the cuda library directory
# installed on the current machine. NOTE: If 64
# bit libraries are installed, this field will
# need to be updated to point to the 64 bit libs
#
# CUDA_GCC_PATH=path/to/dir : The path to the compatible GCC compiler for CUDA.
#
# 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 \
Metropolis/ParallelSim
########################
# 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
##########################
# CUDA Location Settings #
##########################
# The path to the gcc compiler for cuda. This location can change depending on the
# compatible gcc version (preferable to use gcc-4.4.7).
ifeq ($(MAC),1)
CUDA_GCC_PATH ?= /opt/local/bin
LOCAL_INSTALL=1
else
CUDA_GCC_PATH ?= NULL
endif
# Sets the directory where the main cuda libraries and include folders
# are installed. The user can override this value by specifying
# 'CUDA_PATH=/path/to/dir' in the GNU make command to build the program.
#
# This should only be used if the cuda installation is not in the default
# directory.
ifeq ($(LOCAL_INSTALL),1)
CUDA_PATH ?= /usr/local/cuda
else
CUDA_PATH ?= /opt/asn/apps/cuda_5.5
endif
# The path to the cuda include directory where the CUDA header files are found
CUDA_INCLUDE_PATH ?= $(CUDA_PATH)/include
# The path to the cuda bin directory where the executable tools are located,
# such as NVCC and NVPROF
CUDA_BIN_PATH ?= $(CUDA_PATH)/bin
# The path to the cuda lib directory where the shared and static library files
# are located. This location can change depending on the cuda installation and
# the type of operating system (32 bit vs. 64 bit).
#
# NOTE: If the 32-bit cuda installation was used, this value may have to be
# set to point to the 'lib' directory instead of the 'lib64' directory.
ifeq ($(MAC),1)
CUDA_LIB_PATH ?= $(CUDA_PATH)/lib
else
CUDA_LIB_PATH ?= $(CUDA_PATH)/lib64
endif
##############################
# Compiler Specific Settings #
##############################
# Defines the compilers used to compile and link the source files.
# CC will be used to compile C++ files, and NVCC will be used to
# compile CUDA files.
CC := g++
ifeq ($(LOCAL_INSTALL),1)
NVCC := $(CUDA_BIN_PATH)/nvcc
else
NVCC := nvcc
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 %.cu
# Relative search paths for Include Files. We include the root folder, the
# source folder, the testing folder, and the cuda include directory.
IncPaths := . $(SourceDir) $(TestDir) $(CUDA_INCLUDE_PATH)
# Relative search paths for Library Files. We set the cuda lib directory
# as a search path so that cuda code with compile correctly.
LibPaths := $(CUDA_LIB_PATH)
# The CUDA libraries that will be used by the NVCC compiler to link together
# all of the device code into a single package for the host compiler
# to finish linking in the final executable. These library files must
# be located in the CUDA_LIB_PATH directory, else the device code cannot
# be compiled.
CudaLibFlags := -lcudart
# The target device architecture flags specified when compiling and linking
# the CUDA device code
CudaArchitecture := -arch=sm_21
# Compiler specific flags for the C++ compiler when generating .o files
# and when generating .d files for dependency information
CxxFlags := -c
# Compiler specific flags for the CUDA compiler when generating .o files
# and when generating .d files for dependency information
CuFlags := -c -rdc=true $(CudaArchitecture)
# Linker specific flags for the C++ compiler
LCxxFlags :=
# Linker specific flags for the CUDA compiler. CUDA GCC path is specified on Macintosh.
ifeq ($(CUDA_GCC_PATH),NULL)
LCuFlags := -rdc=true $(CudaArchitecture) -lgomp
else
LCuFlags := --compiler-bindir=$(CUDA_GCC_PATH) -rdc=true $(CudaArchitecture) -lgomp
endif
# The debug compiler flags that add symbol and profiling hooks to the
# executable for C++ code
CxxDebugFlags := -g -pg
# The debug compiler flags that add symbol and profiling hooks to the
# executable for both host and device code in CUDA files.
CuDebugFlags := -g -G -pg
# The release build compiler flags that add optimization flags and remove
# all symbol and relocation table information from the executable.
CxxReleaseFlags := -O3 -s -fopenmp
# The release build comiler flags that add optimization flags to the
# executable.
CuReleaseFlags := -O3
#############################
# 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 := -isystem $(GTestDir)/include
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 being set to debug or release. If this define
# is not set by the user, then the build will default to a release build. If
# the user specifies an option other than 'debug' or 'release' then the build
# will default to release build.
ifeq ($(BUILD),debug)
# "Debug" build - set compiling and linking flags
CxxFlags += $(CxxDebugFlags)
LFlags += $(CxxDebugFlags)
CuFlags += $(CuDebugFlags)
LCuFlags += $(CuDebugFlags)
AppDir := $(AppDir)/debug
BuildDir := $(BuildDir)/debug
Definitions += DEBUG
else
# "Release" build - set compiling and linking flags
CxxFlags += $(CxxReleaseFlags)
LFlags += $(CxxReleaseFlags)
CuFlags += $(CuReleaseFlags)
LCuFlags += $(CuReleaseFlags)
BuildDir := $(BuildDir)/release
Definitions += RELEASE
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 library search paths
Libraries := $(addprefix -L, $(LibPaths))
# 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)))
# Get the list of Cuda specific files that will need to be manually
# linked with the host compiler later.
CudaSources := $(filter %.cu, $(Sources))
CudaObjects := $(patsubst %, $(BuildDir)/%.o, $(basename $(CudaSources)))
# 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 either the C++ or CUDA 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) $(Includes) $(Defines) -MM $<
# The command that will generate the dependency file (*.d) output for a given
# CUDA file (*.cu) using the CUDA compiler
create_dep_cu = $(NVCC) $(Includes) $(Defines) -M $<
# 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) $(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 : $(UnitTestName)
$(AppName) : $(Objects) $(ProgramMain) | dirtree
$(NVCC) $^ $(Includes) $(Defines) $(Libraries) -o $(AppDir)/$@ $(LCuFlags)
$(UnitTestName) : $(Objects) $(UnitTestingObjects) $(BuildDir)/cuda_link.o $(ObjDir)/gtest_main.a | dirtree
g++ $^ $(GTestFlags) $(Includes) $(Defines) $(Libraries) -o $(AppDir)/$@ $(CudaLibFlags) -fopenmp
dirtree :
@mkdir -p $(ObjFolders) $(BinDir) $(ObjDir) $(AppDir) $(BuildDir)
clean :
rm -rf $(ObjDir) $(BinDir)
################################
# Object and Source File Rules #
################################
# Here is the rule to build the cuda linked device code. This linked file
# contains all of the CUDA code for the program linked together. This alows
# us to use this file to link together the final program using the host
# compiler rather than using the CUDA compiler.
$(BuildDir)/cuda_link.o : $(CudaObjects) | dirtree
$(NVCC) $(Includes) $(Defines) $(LCuFlags) $^ -dlink -o $@
# 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) $(GTestFlags) -I$(GTestDir) -c \
$(GTestDir)/src/gtest-all.cc -o $@
$(ObjDir)/gtest_main.o : $(GTEST_SRCS_) | dirtree
$(CC) $(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 CUDA and 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
g++ $(CxxFlags) $(GTestFlags) $(Defines) $(Includes) $< -o $@
$(BuildDir)/%.o : %.cu | dirtree
$(NVCC) $(CuFlags) $(Includes) $(Defines) $< -o $@
$(BuildDir)/%.o : %.cpp | dirtree
$(CC) $(CxxFlags) $(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.
# The C++ and CUDA compilers have slightly different syntaxes, so we
# have two functions that handle C++ and CUDA files. Additionally, we
# have a special rule for unit testing because it contains special
# compiler flags. Note: The unit tests will always be in C++.
$(BuildDir)/$(UnitTestDir)/%.dep : $(UnitTestDir)/%.cpp | dirtree
$(SHELL) -ec '$(create_dep_unittest) | $(format_dep)'
$(BuildDir)/%.dep : %.cpp | dirtree
$(SHELL) -ec '$(create_dep_cpp) | $(format_dep)'
$(BuildDir)/%.dep : %.cu | dirtree
$(SHELL) -ec '$(create_dep_cu) | $(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