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
|
# Use bash as the shell
SHELL = /bin/bash
LOCAL_CONFIG_EXISTS = $(shell (test -e config.local.mk && echo 1) || echo 0)
ifeq "${LOCAL_CONFIG_EXISTS}" "1"
CONFIG_MK_FILE = config.local.mk
#CONFIG_MK_FILE = config.windows.mk
else
CONFIG_MK_FILE = config.mk
endif
include $(CONFIG_MK_FILE)
BUILD_TB ?= 0
BUILD_PATH_LIB ?= $(BUILD_PATH)-lib
CXX_LD ?= $(CXX)
CXXFLAGS += -MMD -MP
CXXFLAGS_LIB = $(CXXFLAGS) -fpic
LDFLAGS_LIB = $(LDFLAGS) -shared -Wl,-soname,libspecs.so
BISONFLAGS += --warnings -Wall #-Wcex
# Find all source files in the source directory
SOURCES_BIN = $(shell find $(SRC_PATH) -name '*.cpp' -not -ipath '*/tb/*')
SOURCES_LIB = $(shell find $(SRC_PATH) -name '*.cpp' -not -ipath '*/tb/*' -not -name 'main.cpp' -not -ipath '*/parser/*.cpp')
SOURCES_TB = $(shell find $(SRC_PATH) -name '*.cpp' -ipath '*/tb/*')
SOURCES_TB_MAIN = $(shell find $(SRC_PATH) -name 'alltestbenches.cpp' -ipath '*/tb/*')
SOURCES_ALLFILES = $(shell find $(SRC_PATH) -name '*.cpp' -or -name '*.h')
# Add the whole source directory tree to INCLUDES
INCLUDES += $(addprefix -I,$(shell find $(SRC_PATH) -type d))
# Find all bison/flex source files
# - Note: bison/flex sources must have a matching filename
FLEX_SOURCES = $(shell find $(SRC_PATH) -name '*.l')
BISON_SOURCES = $(shell find $(SRC_PATH) -name '*.y')
# Set the object filenames from the cpp sources
OBJECTS_BIN = $(SOURCES_BIN:$(SRC_PATH)/%.cpp=$(BUILD_PATH)/%.o)
ifeq ($(BUILD_TB), 1)
OBJECTS_BIN += $(SOURCES_TB:$(SRC_PATH)/%.cpp=$(BUILD_PATH)/%.o)
CXXFLAGS += -DBUILD_TB
else
OBJECTS_BIN += $(SOURCES_TB_MAIN:$(SRC_PATH)/%.cpp=$(BUILD_PATH)/%.o)
endif
# Add the objects filenames from the bison/flex sources
OBJECTS_PARSE = $(FLEX_SOURCES:$(SRC_PATH)/%.l=$(BUILD_PATH)/%.yy.o)
OBJECTS_PARSE += $(BISON_SOURCES:$(SRC_PATH)/%.y=$(BUILD_PATH)/%.tab.o)
# Same without main (without testbenches)
OBJECTS_LIB = $(SOURCES_LIB:$(SRC_PATH)/%.cpp=$(BUILD_PATH_LIB)/%.o)
# Set the dependency files that will be used to add header dependencies
DEPS = $(OBJECTS_BIN:.o=.d)
DEPS_PARSE = $(OBJECTS_PARSE:.o=.d)
DEPS_LIB = $(OBJECTS_LIB:.o=.d)
# Set other dependencies that should trigger rebuilding .o files
ADDITIONAL_DEPS = Makefile $(CONFIG_MK_FILE)
# Find the latest trace according to modification time
LATEST_TRACE_NAME = $(shell ls -1rt --group-directories-first traces | tail -1)
# Be verbose
V ?= 0
# Set/Unset the Q flag according to the V flag
ifeq ($(V),1)
Q =
QQ = @
else
Q = @
QQ = @
endif
# Clear known suffixes rules
.SUFFIXES:
# Define phony targets
.PHONY: todos format waves newwaves print-% help cleandoc cleanoldtraces \
cleantraces cleanall clean compiledb view-doc upload-doc doc readme \
all bin lib
# Instruct make not to remove intermediate files from bison/flex compilation
.SECONDARY: $(FLEX_SOURCES:$(SRC_PATH)/%.l=$(BUILD_PATH)/%.yy.h)
.SECONDARY: $(FLEX_SOURCES:$(SRC_PATH)/%.l=$(BUILD_PATH)/%.yy.cpp)
.SECONDARY: $(FLEX_SOURCES:$(SRC_PATH)/%.l=$(BUILD_PATH)/%.tab.h)
.SECONDARY: $(BISON_SOURCES:$(SRC_PATH)/%.y=$(BUILD_PATH)/%.tab.cpp)
# Default rule
all: bin
# Build executable
bin: $(BIN_NAME)
# Build shared library
lib: $(LIB_NAME)
# Link all objects together into executable
$(BIN_NAME): $(OBJECTS_BIN) $(OBJECTS_PARSE)
@echo "Linking binary"
$(Q)$(CCACHE) $(CXX_LD) $(OBJECTS_BIN) $(OBJECTS_PARSE) $(LDFLAGS) -o $@
@echo "Done"
# Link all objects together into library
$(LIB_NAME): $(OBJECTS_LIB)
@echo "Linking library"
$(Q)$(CCACHE) $(CXX_LD) $(OBJECTS_LIB) $(LDFLAGS_LIB) -o $@
@echo "Done"
# Objects depend on their directories
$(OBJECTS_PARSE): $(ADDITIONAL_DEPS) | $(dir $(OBJECTS_PARSE))
# Objects depend on their directories
$(OBJECTS_BIN): $(ADDITIONAL_DEPS) | $(dir $(OBJECTS_BIN)) $(OBJECTS_PARSE)
# Objects depend on their directories
$(OBJECTS_LIB): $(ADDITIONAL_DEPS) | $(dir $(OBJECTS_LIB))
# Rule to create the $(BUILD_PATH) directory
$(BUILD_PATH)/:
$(Q)mkdir -p $@
# Rule to create a subdirectory in $(BUILD_PATH)
$(BUILD_PATH)/%/:
$(Q)mkdir -p $@
# Rule to create the $(BUILD_PATH_LIB) directory
$(BUILD_PATH_LIB)/:
$(Q)mkdir -p $@
# Rule to create a subdirectory in $(BUILD_PATH_LIB)
$(BUILD_PATH_LIB)/%/:
$(Q)mkdir -p $@
# Default .cpp → .o compilation rule
$(BUILD_PATH)/%.o: $(SRC_PATH)/%.cpp
@echo "Compiling $<"
$(Q)$(CCACHE) $(CXX) $(CXXFLAGS) $(INCLUDES) -c $< -o $@
# Default .cpp → .o compilation rule for library
$(BUILD_PATH_LIB)/%.o: $(SRC_PATH)/%.cpp
@echo "Compiling $<"
$(Q)$(CCACHE) $(CXX) $(CXXFLAGS_LIB) $(INCLUDES) -MMD -MP -c $< -o $@
# Special .cpp compilation rule for flex generated sources
%.yy.o: %.yy.cpp %.tab.h
@echo "Compiling $<"
$(Q)$(CCACHE) $(CXX) $(CXXFLAGS) $(INCLUDES) -iquote"$(dir $@)" -c $< -o $@
# Special .cpp compilation rule for bison generated sources
%.tab.o: %.tab.cpp %.yy.h
@echo "Compiling $<"
$(Q)$(CCACHE) $(CXX) $(CXXFLAGS) $(INCLUDES) -iquote"$(dir $@)" -c $< -o $@
# Default .l → .yy.cpp compilation rule
$(BUILD_PATH)/%.yy.cpp: $(SRC_PATH)/%.l | $(dir $($@))
@echo "Lexing $<"
$(Q)flex --header-file="$(@:.cpp=.h)" -o $@ $<
# Default .y → .tab.{h,cpp} compilation rule
$(BUILD_PATH)/%.tab.cpp: $(SRC_PATH)/%.y $(BUILD_PATH)/%.yy.cpp | $(dir $($@))
@echo "Bisoning $<"
$(Q)bison $(BISONFLAGS) --defines="$(@:.cpp=.h)" -o $@ -d $<
# Dependency rule for .tab.h (bison output, needed to compile flex output)
%.tab.h: | %.tab.cpp
@:
# Dependency rule for .yy.h (bison output, needed to compile flex output)
%.yy.h: | %.yy.cpp
@:
#$(ADDITIONAL_DEPS):
#@:
# Add dependency files, if they exist
-include $(DEPS)
-include $(DEPS_LIB)
-include $(DEPS_PARSE)
# Generation of documentation using Doxygen
doc:
@echo "Generating documentation"
@mkdir -p doc/html
@cp -r doc/resources/ doc/html/
$(Q)doxygen doc/Doxyfile
#$(Q)tar -c -f doc/pcm-doc.tar.xz -C doc/html .
# Regenerate compile_commands.json for YouCompleteMe
compiledb: compile_commands.json
# Regenerate compile_commands.json for YouCompleteMe
compile_commands.json: clean
@echo "Generating compile_commands.json"
$(Q)compiledb --verbose make -j8
$(Q)sed -i '/"-MMD"\|"-MP"/d' $@
# Clean build artifacts
clean:
@echo "Removing build artifacts"
$(QQ)#[ ! -d 'build' ] || rm -rf build/
$(QQ)#[ ! -d 'build-lib' ] || rm -rf build-lib/
$(Q)[ ! -d "$(BUILD_PATH)" ] || rm -rf "$(BUILD_PATH)"
$(Q)[ ! -d "$(BUILD_PATH_LIB)" ] || rm -rf "$(BUILD_PATH_LIB)"
# Remove any product of the build (build, trace, doc, bin)
cleanall: clean cleantraces cleandoc
@echo "Removing binary"
$(Q)rm -f Pout.obj Pout.png detector_trace.txt
$(Q)rm -f sim specs libspecs.so
# Clean all traces
cleantraces:
@echo "Removing all traces"
$(Q)find traces/ -maxdepth 1 -type f -and -iname '*.vcd' -delete
# Clean all traces but the newest
cleanoldtraces:
@echo "Removing all traces but newest"
$(Q)find traces/ -maxdepth 1 -iname '*.vcd' -and -type f -and ! -iname "$(LATEST_TRACE_NAME)" -delete
# Clean documentation output
cleandoc:
@echo "Removing generated documentation"
$(Q)rm -rf doc/html doc/pcm-doc.tar.xz
# Show the latest trace with a blank GTKWave config
newwaves:
@echo "Opening latest trace file"
@mkdir -p traces/configs
@bash utils/openwave.sh "traces/$(LATEST_TRACE_NAME)"
# Show the latest trace with a menu to select which GTKWave config to use
waves:
@echo "Opening latest trace file"
@mkdir -p traces/configs
@bash utils/openwave.sh "traces/$(LATEST_TRACE_NAME)" traces/configs
test:
@echo "Running all tests"
$(Q)./specs -t waveguide
$(Q)./specs -t splitter
$(Q)./specs -t merger
$(Q)./specs -t detector
$(Q)./specs -t directional_coupler
$(Q)./specs -t phaseshifter
$(Q)./specs -t mzi
$(Q)./specs -t pcm
$(Q)#./specs -t ring
$(Q)#./specs -t ac_add_drop
$(Q)#./specs -t ac_crow
$(Q)#./specs -t mesh
rc: all
./${BIN_NAME} -fcircuits/rc_mohab.cir
# TODO: add a gate so we don't accidentally "mess up" the working
# directory by shadowing real changes. Maybe do a commit or something
# like this ? or check the git status whether there are changes ?
# Automatic formatting should be automatically run on write, but if
# modifying a file with a different format and re-formatting, changes
# seen by git could be far from obvious to re-read later
# Run clang-format on the source (in place)
format:
@echo "Formatting source"
@clang-format -i $(SOURCES_ALLFILES)
# Print all TODOs found in the source and other files
todos:
@echo "TODO (from code):"
@find $(SRC_PATH) -type f | xargs awk '/TODO:/ {split($$0, arr, "TODO:"); content = arr[2]; print "- " content, "("FILENAME":"FNR")"}' || true
@#find module_definitions/ -type f | xargs awk '/TODO:/ {split($$0, arr, "TODO:"); content = arr[2]; print "- " content, "("FILENAME":"FNR")"}' || true
@find utils/ -type f | xargs awk '/TODO:/ {split($$0, arr, "TODO:"); content = arr[2]; print "- " content, "("FILENAME":"FNR")"}' || true
@cat todo.txt || true
# Print a given variable
print-%:
$(Q)echo $* = $($*)
# FIXME: cannot have ":" in rule descriptions
# Show this help prompt
help:
@ echo
@ echo ' Usage:'
@ echo ''
@ echo ' make <target> [flags...]'
@ echo ''
@ echo ' Targets:'
@ echo ''
@ awk '/^#/{ comment = substr($$0,3) } comment && /^[a-zA-Z][a-zA-Z0-9_-]+ ?:/{ print " ", $$1, comment }' $(MAKEFILE_LIST) | column -t -s ':' | sort
@ echo ''
@ echo ' Flags:'
@ echo ''
@awk '/^#/{ comment = substr($$0,3) } comment && /^[a-zA-Z][a-zA-Z0-9_-]*/ && /\??=/ && /[01]$$/{ print " " $$1 " (default = " $$3 ")",":",comment }' $(MAKEFILE_LIST) | column -t -s ':' | sort
@ echo ''
|