-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMakefile.ext-CFLAGS
254 lines (211 loc) · 8.88 KB
/
Makefile.ext-CFLAGS
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
# #############################################################################
# LOC: Line-Of-Code: Makefile: build tests, example programs, run pytests
# SPDX-License-Identifier: Apache-2.0
#
# Developed based on SplinterDB (https://github.com/vmware/splinterdb) Makefile
# Copy of Makefile, to build just few source files, w/o defining CFLAGS
# inside this Makefile. Build command supplied CFLAGS as generated by the
# Py-gen script using --gen-cflags argument.
# #############################################################################
.DEFAULT_GOAL := all
help::
@echo 'Usage: make [<target>]'
@echo 'Supported targets: clean all run-tests run-test-code'
#
# Verbosity
#
ifndef BUILD_VERBOSE
BUILD_VERBOSE=0
endif
# Setup echo formatting for messages.
ifeq "$(BUILD_VERBOSE)" "1"
COMMAND=
PROLIX=@echo
BRIEF=@ >/dev/null echo
BRIEF_FORMATTED=@ >/dev/null echo
BRIEF_PARTIAL=@echo -n >/dev/null
else ifeq "$(BUILD_VERBOSE)" "0"
COMMAND=@
PROLIX=@ >/dev/null echo
BRIEF=@echo
BRIEF_FORMATTED=@printf
BRIEF_PARTIAL=@echo -n
else
$(error Unknown BUILD_VERBOSE mode "$(BUILD_VERBOSE)". Valid values are "0" or "1". Default is "0")
endif
# Compilers to use
CXX ?= g++
LD ?= g++
# ###################################################################
# SOURCE DIRECTORIES AND FILES, Generator Package
#
LOCPACKAGE = loc
TEST_CODE = test-code
LOCGENPY = $(LOCPACKAGE)/gen_loc_files.py
# ###################################################################
# BUILD DIRECTORIES AND FILES
#
ifndef BUILD_ROOT
BUILD_ROOT := build
endif
#
# Build mode
#
ifndef BUILD_MODE
BUILD_MODE=release
endif
BUILD_DIR := $(BUILD_MODE)
BUILD_PATH=$(BUILD_ROOT)/$(BUILD_DIR)
OBJDIR = $(BUILD_PATH)/obj
BINDIR = $(BUILD_PATH)/bin
# ##############################################################################
# All the generated files (source and header files)
# Ref: https://stackoverflow.com/questions/37781449/including-generated-files-in-makefile-dependencies
# ##############################################################################
# If you list both .h & .c file, generator gets triggered twice. List just one.
SINGLE_FILE_CC_PROGRAM_GENSRC := $(TEST_CODE)/single-file-cc-program/loc_filenames.c
# For this test Makefile, we have just one dependent generated source
GENERATED := $(SINGLE_FILE_CC_PROGRAM_GENSRC)
# ------------------------------------------------------------------------------
# Rule: Use Python generator script to generate the LOC-files
# Rule will be triggered for objects defined to be dependent on $(GENERATED) sources.
# Use the triggering target's dir-path to generate .h / .c files
# ------------------------------------------------------------------------------
$(GENERATED):
@echo
@echo "Invoke LOC-generator triggered by: " $@
$(LOCGENPY) --gen-includes-dir $(dir $@) --gen-source-dir $(dir $@) --src-root-dir $(dir $@) --verbose
@echo
# The rules to generate object files from the generated source files
GENERATED_SRCS := $(filter %.c,$(GENERATED))
GENERATED_OBJS := $(GENERATED_SRCS:%.c=$(OBJDIR)/%.o)
# ###################################################################
# SOURCE DIRECTORIES AND FILES
# ---- Symbols to build test-code sample programs
# -- Pick-up just the C++ sources, used for this test Make procedure
TEST_CODE_SRC := $(shell find $(TEST_CODE) -type f -name *.cc -print)
# -- Sequentially replace src-file extension to generate list of .o's
TEST_CODE_OBJS := $(TEST_CODE_SRC:%.cc=$(OBJDIR)/%.o)
# Grab the "main.c" for each test-code sample program, which will be used
# to construct the list of test-code binaries.
TEST_CODE_BIN_SRC=$(filter %-main.cc, $(TEST_CODE_SRC))
# ----------------------------------------------------------------------------
# Generate location / name of test-code sample program binary, using built-in
# substitution references. test-code/ has sources like:
#
# test-code/single-file-cc-program/single-file-main.cc
#
# Convert this list of *main.c to generate test-code program binary names,
# using the src-dir's name as the program name:
# build/release/bin/test-code/single-file-cc-program
#
TEST_CODE_BINS_TMP := $(TEST_CODE_BIN_SRC:$(TEST_CODE)/%-main.cc=$(BINDIR)/$(TEST_CODE)/%-program)
TEST_CODE_BINS=$(patsubst %program/, %program, $(dir $(TEST_CODE_BINS_TMP)) )
# ###################################################################
# Report build machine details and compiler version for troubleshooting,
# so we see this output for clean builds, especially in CI-jobs.
# ###################################################################
.PHONY : clean tags
clean:
uname -a
$(CXX) --version
rm -rf $(BUILD_ROOT)
find . \( -name "*loc*.c" -o -name "loc*.h" \) -exec rm -rf {} \;
####################################################################
# The main targets
#
all: all-test-code
all-test-code: $(TEST_CODE_BINS)
# ###################################################################
# CFLAGS, LDFLAGS, ETC
#
# -----------------------------------------------------------------------------
# NOTE: Normally we would define this here, so that all source files that
# use LOC-macros would compile cleanly. But the objective of this
# test Makefile is to demonstrate how-to pass CFLAGS externally
# while building the code. Hence, this definition is commented out.
#
# Define CFLAGS to generate the -D clause to define LOC_FILE_INDEX
# using the source file name as input:
# - Replace "-" in filename with "_"
# - Replace "." with "_" (*.c -> *_c, *.cpp -> *_cpp, *.cc -> *_cc)
# -----------------------------------------------------------------------------
# CFLAGS=-DLOC_FILE_INDEX=LOC_$(subst .,_,$(subst -,_,$(notdir $<)))
# -----------------------------------------------------------------------------
# Define the include files' dir-path.
# The LOC-generated .h files will appear in each test-code program's src-dir.
# Use this recursively defined variables to build the path to pick-up both
# forms of #include .h files.
# -----------------------------------------------------------------------------
INCLUDE = -I ./$(dir $<)
# use += here, so that extra flags can be provided via the environment
CFLAGS += -D_GNU_SOURCE -ggdb3 -Wall -Wfatal-errors -Werror
# ###################################################################
# Automatically create directories, based on
# http://ismail.badawi.io/blog/2017/03/28/automatic-directory-creation-in-make/
.SECONDEXPANSION:
.SECONDARY:
%/.:
$(COMMAND) mkdir -p $@
# These targets prevent circular dependencies arising from the
# recipe for building binaries
$(BINDIR)/.:
$(COMMAND) mkdir -p $@
$(BINDIR)/%/.:
$(COMMAND) mkdir -p $@
# ###################################################################
# Dependencies
#
$(GENERATED_OBJS): $(GENERATED)
# ###################################################################
# The dependencies for each test-code sample program
# Every example program of the form bin/test-code/<eg-prog> depends on
# obj/test-code/<eg-prog>/*.o -> *.c
# There can be more than one .o's linked to create test-code example
# program.
# ----
SINGLE_FILE_CC_PROGRAM_TESTSRC := $(shell find $(TEST_CODE)/single-file-cc-program -type f -name *.cc -print)
SINGLE_FILE_CC_PROGRAM_TESTSRC += $(SINGLE_FILE_CC_PROGRAM_GENSRC)
SINGLE_FILE_CC_PROGRAM_OBJS := $(SINGLE_FILE_CC_PROGRAM_TESTSRC:%.cc=$(OBJDIR)/%.o)
$(BINDIR)/$(TEST_CODE)/single-file-cc-program: $(SINGLE_FILE_CC_PROGRAM_OBJS)
$(SINGLE_FILE_CC_PROGRAM_OBJS): $(GENERATED_OBJS)
# ###################################################################
# RECIPES:
# For all-test-code, we need to use -I test-code/<subdir>
# Dependencies for the main executables
COMPILE.cc = $(CXX) $(CFLAGS) $(INCLUDE) -c
# ----
# Compile each .cc file into its .o
# Also define a dependency on the dir in which .o will be produced (@D).
# The secondary expansion will invoke mkdir to create output dirs first.
$(OBJDIR)/%.o: %.cc | $$(@D)/.
$(BRIEF_FORMATTED) "%-20s %-50s [%s]\n" Compiling $< $@
$(COMMAND) $(COMPILE.cc) $< -o $@
$(PROLIX) # blank line
# ----
# Link .o's to product running binary
# Define dependency on output dir existing, so secondary expansion will
# trigger mkdir to create bin/s output dir.
# If you add "$^" to 'Linking' message, you will see list of .o's being linked
$(BINDIR)/%: | $$(@D)/.
$(BRIEF_FORMATTED) "%-20s %s\n" Linking $@
$(COMMAND) $(LD) $(LDFLAGS) $^ -o $@ $(LIBS)
$(PROLIX) # blank line
# ----
ifeq "$(BUILD_VERBOSE)" "1"
@echo
$(info $$TEST_CODE_SRC = [${TEST_CODE_SRC}])
$(info $$TEST_CODE_OBJS = [${TEST_CODE_OBJS}])
$(info $$TEST_CODE_BIN_SRC = [${TEST_CODE_BIN_SRC}])
$(info $$TEST_CODE_BINS = [${TEST_CODE_BINS}])
$(info $$GENERATED_OBJS = [${GENERATED_OBJS}])
endif
# ###################################################################
# Testing
#
.PHONY: install
run-tests: run-test-code
run-test-code: all-test-code
@echo
@echo "**** Run sample test-code programs ****"
for i in $(TEST_CODE_BINS); do echo " "; echo "-- Executing $$i";$$i || exit; done