• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1DOWNLOAD_SCRIPT := $(MAKEFILE_DIR)/download_and_extract.sh
2
3# Reverses a space-separated list of words.
4reverse = $(if $(1),$(call reverse,$(wordlist 2,$(words $(1)),$(1)))) $(firstword $(1))
5
6# Get macros only (i.e. the ones starting with -D) from two lists and remove duplicates
7getmacros = $(patsubst -D%,%,$(filter -D%,$(sort $(filter -D%, $(1)) $(filter -D%, $(2)))))
8
9# Look for platform or target-specific implementation files to replace reference
10# implementations with, given a tag. These are expected to occur in subfolders
11# of a directory where a reference implementation exists, and have the same
12# interface and header file. For example,
13# tensorflow/lite/micro/examples/micro_speech/audio_provider.cc
14# defines a module for supplying audio data, but since no platform or OS can be
15# presumed, it just always returns zeroes for its samples. The MacOS-specific
16# tensorflow/lite/micro/examples/micro_speech/osx/audio_provider.cc
17# has an implementation that relies on CoreAudio, and there are equivalent
18# versions for other operating systems.
19# The specific implementation yielded by the first tag in the list that produces
20# a match is returned, else the reference version if none of the tags produce a
21# match.
22# All lists of source files are put through this substitution process with the
23# tags of their target OS and architecture, so that implementations can be added
24# by simply placing them in the file tree, with no changes to the build files
25# needed.
26# One confusing thing about this implementation is that we're using wildcard to
27# act as a 'does file exist?' function, rather than expanding an expression.
28# Wildcard will return an empty string if given a plain file path with no actual
29# wildcards, if the file doesn't exist, so taking the first word of the list
30# between that and the reference path will pick the specialized one if it's
31# available.
32# Another fix is that originally if neither file existed(either the original or
33# a specialized version) this would return an empty string.Because this is
34# sometimes called on third party library files before they've been downloaded,
35# this caused mysterious errors, so an initial if conditional was added so that
36# specializations are only looked for if the original file exists.
37substitute_specialized_implementation = \
38  $(if $(wildcard $(1)),$(firstword $(wildcard $(dir $(1))$(2)/$(notdir $(1))) $(wildcard $(1))),$(1))
39substitute_specialized_implementations = \
40  $(foreach source,$(1),$(call substitute_specialized_implementation,$(source),$(2)))
41
42# Tests and project generation targets use this entrypoint for to get the
43# specialized sources. It should be avoided for any new functionality.
44# The only argument is a list of file paths.
45specialize = $(call substitute_specialized_implementations,$(1),$(TARGET))
46
47# TODO(b/143904317): It would be better to have the dependency be
48# THIRD_PARTY_TARGETS instead of third_party_downloads. However, that does not
49# quite work for the generate_project functions.
50#
51# Creates a set of rules to build a standalone makefile project for an
52# executable, including all of the source and header files required in a
53# separate folder and a simple makefile.
54# Arguments are:
55# 1 - Project type (make, mbed, etc).
56# 2 - Project file template name.
57# 3 - Name of executable.
58# 4 - List of C/C++ source files needed to build the target.
59# 5 - List of C/C++ header files needed to build the target.
60# 6 - Linker flags required.
61# 7 - C++ compilation flags needed.
62# 8 - C compilation flags needed.
63# 9 - Target Toolchian root directory
64# 10 - Target Toolchain prefix
65# Calling eval on the output will create a <Name>_makefile target that you
66# can invoke to create the standalone project.
67define generate_project
68$(PRJDIR)$(3)/$(1)/%: % third_party_downloads
69	@mkdir -p $$(dir $$@)
70	@cp $$< $$@
71
72$(PRJDIR)$(3)/cmake/boards/%: tensorflow/lite/micro/examples/$(3)/zephyr_riscv/boards/%
73	@mkdir -p $$(dir $$@)
74	@cp $$< $$@
75
76$(PRJDIR)$(3)/cmake/%: tensorflow/lite/micro/examples/$(3)/zephyr_riscv/%
77	@mkdir -p $$(dir $$@)
78	@cp $$< $$@
79
80$(PRJDIR)$(3)/$(1)/third_party/%: tensorflow/lite/micro/tools/make/downloads/% third_party_downloads
81	@mkdir -p $$(dir $$@)
82	@cp $$< $$@
83
84$(PRJDIR)$(3)/$(1)/%: tensorflow/lite/micro/tools/make/templates/%.tpl
85	@mkdir -p $$(dir $$@)
86	@sed -E 's#\%\{SRCS\}\%#$(4)#g' $$< | \
87	sed -E 's#\%\{EXECUTABLE\}\%#$(3)#g' | \
88	sed -E 's#\%\{LINKER_FLAGS\}\%#$(6)#g' | \
89	sed -E 's#\%\{CXX_FLAGS\}\%#$(7)#g' | \
90	sed -E 's#\%\{CC_FLAGS\}\%#$(8)#g' | \
91	sed -E 's#\%\{TARGET_TOOLCHAIN_ROOT\}\%#$(9)#g' | \
92	sed -E 's#\%\{TARGET_TOOLCHAIN_PREFIX\}\%#$(10)#g' > $$@
93
94$(PRJDIR)$(3)/$(1)/keil_project.uvprojx: tensorflow/lite/micro/tools/make/templates/keil_project.uvprojx.tpl
95	@mkdir -p $$(dir $$@)
96	@python tensorflow/lite/micro/tools/make/generate_keil_project.py \
97        --input_template=$$< --output_file=$$@ --executable=$(3) \
98        --srcs="$(4)" --hdrs="$(5)" --include_paths="$$(PROJECT_INCLUDES)"
99
100$(PRJDIR)$(3)/$(1)/.vscode/tasks.json : tensorflow/lite/micro/tools/make/templates/tasks.json.$(1).tpl
101	@mkdir -p $$(dir $$@)
102	@cp $$< $$@
103
104generate_$(3)_$(1)_project: $(addprefix $(PRJDIR)$(3)/$(1)/, $(4) $(5) $(2))
105ifeq (mbed, $(1))
106	$(eval macrolist := $(call getmacros, $7, $8))
107	$(eval jsonfilename := $(PRJDIR)$(3)/$(1)/mbed_app)
108	@awk 'FNR==NR{ if (/}/) p=NR; next} 1; FNR==(p-1){ n=split("$(macrolist)",a," "); print("    ,\"macros\": [");for (i=1; i <= n; i++){ printf("        \"%s\"", a[i]); if(i<n){printf(",\n")}}printf("\n    ]\n")}' \
109        $(jsonfilename).json $(jsonfilename).json > $(jsonfilename).tmp && mv $(jsonfilename).tmp $(jsonfilename).json
110endif
111
112list_$(3)_$(1)_files:
113	@echo $(4) $(5)
114
115ALL_PROJECT_TARGETS += generate_$(3)_$(1)_project
116endef
117
118# Creates a set of rules to build a standalone makefile project for the ARC platform
119# including all of the source and header files required in a
120# separate folder and a simple makefile.
121# Arguments are:
122# 1 - Project type (make, mbed, etc).
123# 2 - Project file template name.
124# 3 - Name of executable.
125# 4 - List of C/C++ source files needed to build the target.
126# 5 - List of C/C++ header files needed to build the target.
127# 6 - Linker flags required.
128# 7 - C++ compilation flags needed.
129# 8 - C compilation flags needed.
130
131# Calling eval on the output will create a <Name>_makefile target that you
132# can invoke to create the standalone project.
133define generate_arc_project
134
135ifeq ($(TARGET_ARCH), arc)
136
137$(PRJDIR)$(3)/$(1)/Makefile: tensorflow/lite/micro/tools/make/templates/arc/arc_app_makefile.tpl
138	@mkdir -p $$(dir $$@)
139	@sed -E 's#\%\{SRCS\}\%#$(4)#g' $$< | \
140	sed -E 's#\%\{CC\}\%#$(CC_TOOL)#g' | \
141	sed -E 's#\%\{CXX\}\%#$(CXX_TOOL)#g' | \
142	sed -E 's#\%\{LD\}\%#$(LD_TOOL)#g' | \
143	sed -E 's#\%\{EXECUTABLE\}\%#$(3).elf#g' | \
144	sed -E 's#\%\{LINKER_FLAGS\}\%#$(6)#g' | \
145	sed -E 's#\%\{CXX_FLAGS\}\%#$(7)#g' | \
146	sed -E 's#\%\{CC_FLAGS\}\%#$(8)#g' | \
147	sed -E 's#\%\{EXTRA_APP_SETTINGS\}\%#$(ARC_EXTRA_APP_SETTINGS)#g' | \
148	sed -E 's#\%\{EXTRA_APP_RULES\}\%#$(ARC_EXTRA_APP_RULES)#g' | \
149	sed -E 's#\%\{BIN_DEPEND\}\%#$(ARC_BIN_DEPEND)#g' | \
150	sed -E 's#\%\{BIN_RULE\}\%#$(ARC_BIN_RULE)#g' | \
151	sed -E 's#\%\{EXTRA_RM_TARGETS\}\%#$(ARC_EXTRA_RM_TARGETS)#g' | \
152	sed -E 's#\%\{APP_RUN_CMD\}\%#$(ARC_APP_RUN_CMD)#g' | \
153	sed -E 's#\%\{APP_DEBUG_CMD\}\%#$(ARC_APP_DEBUG_CMD)#g' | \
154	sed -E 's#\%\{EXTRA_EXECUTE_RULES\}\%#$(ARC_EXTRA_EXECUTE_RULES)#g' > $$@
155
156$(PRJDIR)$(3)/$(1)/%: tensorflow/lite/micro/tools/make/templates/arc/%.tpl
157	@cp $$< $$@
158
159$(foreach var,$(ARC_TARGET_COPY_FILES), $(eval $(call path_changing_copy_file,\
160    $(PRJDIR)$(3)/$(1)/$(word 1, $(subst !, ,$(var))),\
161    $(word 2, $(subst !, ,$(var))))))
162
163endif
164endef
165
166
167define generate_ceva_bx1_project
168ifeq ($(TARGET), ceva)
169ifeq ($(TARGET_ARCH), CEVA_BX1)
170
171$(PRJDIR)$(3)/$(1)/Makefile: tensorflow/lite/micro/tools/make/templates/ceva/ceva_app_makefile_v18.0.5.tpl
172	@mkdir -p $$(dir $$@)
173	@sed -E 's#\%\{SRCS\}\%#$(4)#g' $$< | \
174	sed -E 's#\%\{CC\}\%#$(CC_TOOL)#g' | \
175	sed -E 's#\%\{CXX\}\%#$(CXX_TOOL)#g' | \
176	sed -E 's#\%\{LD\}\%#$(LD_TOOL)#g' | \
177	sed -E 's#\%\{EXECUTABLE\}\%#$(3).elf#g' | \
178	sed -E 's#\%\{LD_FLAGS\}\%#$(6)#g' | \
179	sed -E 's#\%\{CXX_FLAGS\}\%#$(7)#g' | \
180	sed -E 's#\%\{CC_FLAGS\}\%#$(8)#g' > $$@
181
182$(PRJDIR)$(3)/$(1)/%: tensorflow/lite/micro/tools/make/templates/ceva/%.tpl
183	@cp $$< $$@
184
185$(foreach var,$(CEVA_TARGET_FILES_DIRS),$(eval $(call path_changing_copy_file,$(PRJDIR)$(3)/$(1),$(var))))
186
187endif
188endif
189endef
190
191
192
193
194
195# Creates a set of rules to build a standalone Arduino project for an
196# executable, including all of the source and header files required in a
197# separate folder and a simple makefile.
198# Arguments are:
199# 1 - Project file template names.
200# 2 - Name of executable.
201# 3 - List of C/C++ source files needed to build the target.
202# 4 - List of C/C++ header files needed to build the target.
203# 5 - Linker flags required.
204# 6 - C++ compilation flags needed.
205# 7 - C compilation flags needed.
206# Calling eval on the output will create a <Name>_makefile target that you
207# can invoke to create the standalone project.
208define generate_arduino_project
209
210$(PRJDIR)$(2)/arduino/examples/%.c: tensorflow/lite/micro/examples/%.c
211	@mkdir -p $$(dir $$@)
212	@python tensorflow/lite/micro/tools/make/transform_source.py \
213        --platform=arduino \
214        --is_example_source \
215        --source_path="$$<" \
216        --third_party_headers="$(4)" < $$< > $$@
217
218$(PRJDIR)$(2)/arduino/examples/%.cpp: tensorflow/lite/micro/examples/%.cc
219	@mkdir -p $$(dir $$@)
220	@python tensorflow/lite/micro/tools/make/transform_source.py \
221        --platform=arduino \
222        --is_example_source \
223        --source_path="$$<" \
224        --third_party_headers="$(4)" < $$< > $$@
225
226$(PRJDIR)$(2)/arduino/examples/%.h: tensorflow/lite/micro/examples/%.h
227	@mkdir -p $$(dir $$@)
228	@python tensorflow/lite/micro/tools/make/transform_source.py \
229        --platform=arduino \
230        --is_example_source \
231        --source_path="$$<" \
232        --third_party_headers="$(4)" < $$< > $$@
233
234$(PRJDIR)$(2)/arduino/examples/%/main.ino: tensorflow/lite/micro/examples/%/main_functions.cc
235	@mkdir -p $$(dir $$@)
236	@python tensorflow/lite/micro/tools/make/transform_source.py \
237        --platform=arduino \
238        --is_example_ino \
239        --source_path="$$<" \
240        --third_party_headers="$(4)" < $$< > $$@
241
242$(PRJDIR)$(2)/arduino/src/%.cpp: %.cc
243	@mkdir -p $$(dir $$@)
244	@python tensorflow/lite/micro/tools/make/transform_source.py \
245        --platform=arduino \
246        --third_party_headers="$(4)" < $$< > $$@
247
248$(PRJDIR)$(2)/arduino/src/%.h: %.h third_party_downloads
249	@mkdir -p $$(dir $$@)
250	@python tensorflow/lite/micro/tools/make/transform_source.py \
251        --platform=arduino \
252        --third_party_headers="$(4)" < $$< > $$@
253
254$(PRJDIR)$(2)/arduino/LICENSE: LICENSE
255	@mkdir -p $$(dir $$@)
256	@cp $$< $$@
257
258$(PRJDIR)$(2)/arduino/src/%: % third_party_downloads
259	@mkdir -p $$(dir $$@)
260	@python tensorflow/lite/micro/tools/make/transform_source.py \
261        --platform=arduino \
262        --third_party_headers="$(4)" < $$< > $$@
263
264$(PRJDIR)$(2)/arduino/src/third_party/%: tensorflow/lite/micro/tools/make/downloads/% third_party_downloads
265	@mkdir -p $$(dir $$@)
266	@python tensorflow/lite/micro/tools/make/transform_source.py \
267        --platform=arduino \
268        --third_party_headers="$(4)" < $$< > $$@
269
270$(PRJDIR)$(2)/arduino/src/third_party/%.cpp: tensorflow/lite/micro/tools/make/downloads/%.cc third_party_downloads
271	@mkdir -p $$(dir $$@)
272	@python tensorflow/lite/micro/tools/make/transform_source.py \
273        --platform=arduino \
274        --third_party_headers="$(4)" < $$< > $$@
275
276$(PRJDIR)$(2)/arduino/src/third_party/flatbuffers/include/flatbuffers/base.h: tensorflow/lite/micro/tools/make/downloads/flatbuffers/include/flatbuffers/base.h third_party_downloads
277	@mkdir -p $$(dir $$@)
278	@python tensorflow/lite/micro/tools/make/transform_source.py \
279        --platform=arduino \
280        --third_party_headers="$(4)" < $$< | \
281        sed -E 's/utility\.h/utility/g' > $$@
282
283$(PRJDIR)$(2)/arduino/src/third_party/kissfft/kiss_fft.h: tensorflow/lite/micro/tools/make/downloads/kissfft/kiss_fft.h third_party_downloads
284	@mkdir -p $$(dir $$@)
285	@python tensorflow/lite/micro/tools/make/transform_source.py \
286        --platform=arduino \
287        --third_party_headers="$(4)" < $$< | \
288        sed -E 's@#include <string.h>@//#include <string.h> /* Patched by helper_functions.inc for Arduino compatibility */@g' > $$@
289
290$(PRJDIR)$(2)/arduino/%: tensorflow/lite/micro/tools/make/templates/%
291	@mkdir -p $$(dir $$@)
292	@sed -E 's#\%\{SRCS\}\%#$(3)#g' $$< | \
293	sed -E 's#\%\{EXECUTABLE\}\%#$(2)#g' | \
294	sed -E 's#\%\{LINKER_FLAGS\}\%#$(5)#g' | \
295	sed -E 's#\%\{CXX_FLAGS\}\%#$(6)#g' | \
296	sed -E 's#\%\{CC_FLAGS\}\%#$(7)#g' > $$@
297
298$(PRJDIR)$(2)/arduino/examples/$(2)/$(2).ino: tensorflow/lite/micro/tools/make/templates/arduino_example.ino
299	@mkdir -p $$(dir $$@)
300	@cp $$< $$@
301
302$(PRJDIR)$(2)/arduino/src/TensorFlowLite.h: tensorflow/lite/micro/tools/make/templates/TensorFlowLite.h
303	@mkdir -p $$(dir $$@)
304	@cp $$< $$@
305
306# This would be cleaner if we broke up the list of dependencies into variables,
307# but these get hard to define with the evaluation approach used to define make
308# functions.
309generate_$(2)_arduino_project: \
310$(addprefix $(PRJDIR)$(2)/arduino/,         \
311$(patsubst tensorflow/%,src/tensorflow/%,\
312$(patsubst examples/%/main_functions.cpp,examples/%/main.ino,\
313$(patsubst examples/%_test.cpp,examples/%_test.ino,\
314$(patsubst tensorflow/lite/micro/examples/%,examples/%,\
315$(patsubst third_party/%,src/third_party/%,\
316$(patsubst %.cc,%.cpp,$(3))))))))                                     \
317$(addprefix $(PRJDIR)$(2)/arduino/, \
318$(patsubst tensorflow/%,src/tensorflow/%,\
319$(patsubst tensorflow/lite/micro/examples/%,examples/%,\
320$(patsubst third_party/%,src/third_party/%,$(4))))) \
321$(addprefix $(PRJDIR)$(2)/arduino/,$(1)) \
322$(PRJDIR)$(2)/arduino/src/TensorFlowLite.h
323
324generate_$(2)_arduino_library_zip: generate_$(2)_arduino_project
325	cp -r $(PRJDIR)$(2)/arduino $(PRJDIR)$(2)/tensorflow_lite
326	python tensorflow/lite/micro/tools/make/fix_arduino_subfolders.py $(PRJDIR)$(2)/tensorflow_lite
327	@cd $(PRJDIR)$(2) && zip -q -r tensorflow_lite.zip tensorflow_lite
328
329ALL_PROJECT_TARGETS += $(if $(findstring _test,$(2)),,generate_$(2)_arduino_library_zip)
330
331    ARDUINO_LIBRARY_ZIPS += $(if $(findstring _mock,$(2)),,$(if $(findstring _test,$(2)),,$(PRJDIR)$(2)/tensorflow_lite.zip))
332
333endef
334
335# Creates a set of rules to build a standalone ESP-IDF project for an
336# executable, including all of the source and header files required in a
337# separate folder.
338# Arguments are:
339# 1 - Project file template names.
340# 2 - Name of executable.
341# 3 - List of C/C++ source files needed to build the TF Micro component.
342# 4 - List of C/C++ header files needed to build the TF Micro component.
343# 5 - List of C/C++ source files needed to build this particular project.
344# 6 - List of C/C++ header files needed to build this particular project.
345# 7 - Linker flags required.
346# 8 - C++ compilation flags needed.
347# 9 - C compilation flags needed.
348# 10 - List of includes.
349define generate_esp_project
350$(PRJDIR)$(2)/esp-idf/LICENSE: LICENSE
351	@mkdir -p $$(dir $$@)
352	@cp $$< $$@
353
354$(PRJDIR)$(2)/esp-idf/%: tensorflow/lite/micro/examples/$(2)/esp/%
355	@mkdir -p $$(dir $$@)
356	@cp $$< $$@
357
358$(PRJDIR)$(2)/esp-idf/main/%.cc: tensorflow/lite/micro/examples/$(2)/%.cc
359	@mkdir -p $$(dir $$@)
360	@python tensorflow/lite/micro/tools/make/transform_source.py \
361        --platform=esp \
362        --is_example_source \
363        --source_path="$$<" \
364        < $$< > $$@
365
366$(PRJDIR)$(2)/esp-idf/main/%.h: tensorflow/lite/micro/examples/$(2)/%.h
367	@mkdir -p $$(dir $$@)
368	@python tensorflow/lite/micro/tools/make/transform_source.py \
369        --platform=esp \
370        --is_example_source \
371        --source_path="$$<" \
372        < $$< > $$@
373
374$(PRJDIR)$(2)/esp-idf/main/%: tensorflow/lite/micro/examples/$(2)/%
375	@mkdir -p $$(dir $$@)
376	@cp $$< $$@
377
378$(PRJDIR)$(2)/esp-idf/components/tfmicro/%: % third_party_downloads
379	@mkdir -p $$(dir $$@)
380	@cp $$< $$@
381
382$(PRJDIR)$(2)/esp-idf/components/tfmicro/third_party/%: tensorflow/lite/micro/tools/make/downloads/% third_party_downloads
383	@mkdir -p $$(dir $$@)
384	@cp $$< $$@
385
386$(PRJDIR)$(2)/esp-idf/sdkconfig.defaults: tensorflow/lite/micro/examples/$(2)/esp/sdkconfig.defaults
387	@mkdir -p $$(dir $$@)
388	@cp $$< $$@
389
390$(PRJDIR)$(2)/esp-idf/%: tensorflow/lite/micro/tools/make/templates/esp/%.tpl
391# Split the sources into 2 components:
392# - Main component contains only the example's sources, relative from its dir.
393# - TFL Micro component contains everything but the example sources.
394  $(eval MAIN_SRCS := $(filter tensorflow/lite/micro/examples/%,$(5)))
395  $(eval MAIN_SRCS_RELATIVE := $(patsubst tensorflow/lite/micro/examples/$(2)/%,%,$(MAIN_SRCS)))
396  $(eval TFLM_SRCS := $(filter-out tensorflow/lite/micro/examples/%,$(5)) $(3))
397
398	@mkdir -p $$(dir $$@)
399	@sed -E 's#\%\{COMPONENT_SRCS\}\%#$(TFLM_SRCS)#g' $$< | \
400	sed -E 's#\%\{MAIN_SRCS\}\%#$(MAIN_SRCS_RELATIVE)#g' | \
401	sed -E 's#\%\{EXECUTABLE\}\%#$(2)#g' | \
402	sed -E 's#\%\{COMPONENT_INCLUDES\}\%#$(10)#g' | \
403	sed -E 's#\%\{LINKER_FLAGS\}\%#$(7)#g' | \
404	sed -E 's#\%\{CXX_FLAGS\}\%#$(8)#g' | \
405	sed -E 's#\%\{CC_FLAGS\}\%#$(9)#g' > $$@
406
407generate_$(2)_esp_project: \
408$(addprefix $(PRJDIR)$(2)/esp-idf/,\
409$(patsubst tensorflow/%,components/tfmicro/tensorflow/%,\
410$(patsubst third_party/%,components/tfmicro/third_party/%,\
411$(patsubst tensorflow/lite/micro/examples/$(2)/%,main/%,$(3) $(4) $(5) $(6))))) \
412$(addprefix $(PRJDIR)$(2)/esp-idf/,$(1))
413
414ALL_PROJECT_TARGETS += generate_$(2)_esp_project
415endef
416
417# Specialized version of generate_project for TF Lite Micro test targets that
418# automatically includes standard library files, so you just need to pass the
419# test name and any extra source files required.
420# Arguments are:
421# 1 - Name of test.
422# 2 - C/C++ source files implementing the test.
423# 3 - C/C++ header files needed for the test.
424# Calling eval on the output will create targets that you can invoke to
425# generate the standalone project.
426define generate_microlite_projects
427$(call generate_project,make,$(MAKE_PROJECT_FILES) $($(1)_MAKE_PROJECT_FILES),$(1),$(MICROLITE_CC_SRCS) $(THIRD_PARTY_CC_SRCS) $(2),$(MICROLITE_CC_HDRS) $(THIRD_PARTY_CC_HDRS) $(MICROLITE_TEST_HDRS) $(3),$(LDFLAGS) $(MICROLITE_LIBS),$(CXXFLAGS) $(GENERATED_PROJECT_INCLUDES), $(CCFLAGS) $(GENERATED_PROJECT_INCLUDES),$(TARGET_TOOLCHAIN_ROOT),$(TARGET_TOOLCHAIN_PREFIX))
428$(call generate_arc_project,make,$(MAKE_PROJECT_FILES) $($(1)_MAKE_PROJECT_FILES),$(1),$(MICROLITE_CC_SRCS) $(THIRD_PARTY_CC_SRCS) $(2),$(MICROLITE_CC_HDRS) $(THIRD_PARTY_CC_HDRS) $(MICROLITE_TEST_HDRS) $(3),$(LDFLAGS) $(GENERATED_PROJECT_LIBS),$(CXXFLAGS) $(GENERATED_PROJECT_INCLUDES), $(CCFLAGS) $(GENERATED_PROJECT_INCLUDES))
429$(call generate_ceva_bx1_project,make,$(MAKE_PROJECT_FILES) $($(1)_MAKE_PROJECT_FILES),$(1),$(MICROLITE_CC_SRCS) $(THIRD_PARTY_CC_SRCS) $(2),$(MICROLITE_CC_HDRS) $(THIRD_PARTY_CC_HDRS) $(MICROLITE_TEST_HDRS) $(3),$(LDFLAGS) $(GENERATED_PROJECT_LIBS),$(CXXFLAGS) $(GENERATED_PROJECT_INCLUDES), $(CCFLAGS) $(GENERATED_PROJECT_INCLUDES))
430$(call generate_project,mbed,$(MBED_PROJECT_FILES) $($(1)_MBED_PROJECT_FILES),$(1),$(MICROLITE_CC_SRCS) $(THIRD_PARTY_CC_SRCS) $(2),$(MICROLITE_CC_HDRS) $(THIRD_PARTY_CC_HDRS) $(MICROLITE_TEST_HDRS) $(3),$(MICROLITE_LIBS),$(CXXFLAGS),$(CCFLAGS),$(TARGET_TOOLCHAIN_ROOT),$(TARGET_TOOLCHAIN_PREFIX))
431$(call generate_project,keil,$(KEIL_PROJECT_FILES) $($(1)_KEIL_PROJECT_FILES),$(1),$(MICROLITE_CC_SRCS) $(THIRD_PARTY_CC_SRCS) $(2),$(MICROLITE_CC_HDRS) $(THIRD_PARTY_CC_HDRS) $(MICROLITE_TEST_HDRS) $(3),$(MICROLITE_LIBS),$(CXXFLAGS),$(CCFLAGS),$(TARGET_TOOLCHAIN_ROOT),$(TARGET_TOOLCHAIN_PREFIX))
432ifeq (,$(findstring _benchmark,$(1)))
433  $(call generate_arduino_project,$(ARDUINO_PROJECT_FILES) $($(1)_ARDUINO_PROJECT_FILES),$(1),$(MICROLITE_CC_SRCS) $(THIRD_PARTY_CC_SRCS) $(2),$(MICROLITE_CC_HDRS) $(THIRD_PARTY_CC_HDRS) $(MICROLITE_TEST_HDRS) $(3),$(MICROLITE_LIBS),$(CXXFLAGS),$(CCFLAGS))
434endif
435$(call generate_esp_project,$(ESP_PROJECT_FILES) $($(1)_ESP_PROJECT_FILES),$(1),$(MICROLITE_CC_SRCS) $(THIRD_PARTY_CC_SRCS),$(MICROLITE_CC_HDRS) $(THIRD_PARTY_CC_HDRS) $(MICROLITE_TEST_HDRS),$(2),$(3),$(MICROLITE_LIBS),$(CXXFLAGS),$(CCFLAGS),$(PROJECT_INCLUDES))
436endef
437
438# Handles the details of generating a binary target, including specializing
439# for the current platform, and generating project file targets.
440#
441# Note that while the function is called microlite_test, it is used for both
442# test and non-test binaries.
443
444# Files that end with _test are added as test targets (i.e. can be executed with
445# make test_<target>. ALl others can be executed with make run_<target>
446#
447# Arguments are:
448# 1 - Name of target.
449# 2 - C/C++ source files
450# 3 - C/C++ header files
451# 4 - if "exclude", then the non-test target will be excluded from
452#     MICROLITE_BUILD_TARGETS. This exception is needed because not all the
453#     microlite_test targets (e.g. the examples) are buildable on all platforms.
454# Calling eval on the output will create the targets that you need.
455define microlite_test
456ifeq (,$(findstring _test, $(1)))
457	$(eval $(call generate_project_third_party_parsing))
458endif
459
460$(1)_LOCAL_SRCS := $(2)
461$(1)_LOCAL_SRCS := $$(call specialize,$$($(1)_LOCAL_SRCS))
462ALL_SRCS += $$($(1)_LOCAL_SRCS)
463$(1)_LOCAL_HDRS := $(3)
464$(1)_LOCAL_OBJS := $$(addprefix $$(OBJDIR), \
465$$(patsubst %.cc,%.o,$$(patsubst %.c,%.o,$$($(1)_LOCAL_SRCS))))
466$(1)_BINARY := $$(BINDIR)$(1)
467$$($(1)_BINARY): $$($(1)_LOCAL_OBJS) $$(MICROLITE_LIB_PATH)
468	@mkdir -p $$(dir $$@)
469	$$(CXX) $$(CXXFLAGS) $$(INCLUDES) \
470	-o $$($(1)_BINARY) $$($(1)_LOCAL_OBJS) \
471	$$(MICROLITE_LIB_PATH) $$(LDFLAGS) $$(MICROLITE_LIBS)
472$(1): $$($(1)_BINARY)
473$(1)_bin: $$($(1)_BINARY).bin
474
475ifneq (,$(findstring _test,$(1)))
476  MICROLITE_TEST_TARGETS += test_$(1)
477  MICROLITE_BUILD_TARGETS += $$($(1)_BINARY)
478
479test_$(1): $$($(1)_BINARY)
480	$$(TEST_SCRIPT) $$($(1)_BINARY) $$(TEST_PASS_STRING) $$(TARGET)
481
482else
483  ifeq ($(findstring exclude,$(4)),)
484    MICROLITE_BUILD_TARGETS += $$($(1)_BINARY)
485  endif
486
487run_$(1): $$($(1)_BINARY)
488	$$(TEST_SCRIPT) $$($(1)_BINARY) non_test_binary $$(TARGET)
489endif
490
491$(eval $(call generate_microlite_projects,$(1),$(call specialize,$(2)),$(3)))
492endef
493
494# Adds a dependency for a third-party library that needs to be downloaded from
495# an external source.
496# Arguments are:
497# 1 - URL to download archive file from (can be .zip, .tgz, or .bz).
498# 2 - MD5 sum of archive, to check integrity. Use md5sum tool to generate.
499# 3 - Folder name to unpack library into, inside tf/l/x/m/t/downloads root.
500# 4 - Optional patching action, must match clause in download_and_extract.sh.
501# 5 - Optional patching action parameter
502# These arguments are packed into a single '!' separated string, so no element
503# can contain a '!'.
504define add_third_party_download
505THIRD_PARTY_DOWNLOADS += $(1)!$(2)!tensorflow/lite/micro/tools/make/downloads/$(3)!$(4)!$(5)
506endef
507
508# Unpacks an entry in a list of strings created by add_third_party_download, and
509# defines a dependency rule to download the library. The download_and_extract.sh
510# script is used to handle to downloading and unpacking.
511# 1 - Information about the library, separated by '!'s.
512define create_download_rule
513$(word 3, $(subst !, ,$(1))):
514	$(DOWNLOAD_SCRIPT) $(subst !, ,$(1))
515THIRD_PARTY_TARGETS += $(word 3, $(subst !, ,$(1)))
516endef
517
518# Recursively find all files of given pattern
519# Arguments are:
520# 1 - Starting path
521# 2 - File pattern, e.g: *.h
522recursive_find = $(wildcard $(1)$(2)) $(foreach dir,$(wildcard $(1)*),$(call recursive_find,$(dir)/,$(2)))
523
524
525# Modifies the Makefile to include all third party Srcs so that generate
526# projects will create a Makefile that can be immediatley compiled without
527# modification
528define generate_project_third_party_parsing
529
530ifeq ($$(PARSE_THIRD_PARTY), true)
531# Get generated src includes with update path to third party
532THIRD_PARTY_CC_SRCS += $$(filter $$(MAKEFILE_DIR)/downloads/%, $$(MICROLITE_CC_SRCS))
533MICROLITE_CC_SRCS := $$(filter-out $$(THIRD_PARTY_CC_SRCS), $$(MICROLITE_CC_SRCS))
534THIRD_PARTY_CC_SRCS :=  $$(sort $$(patsubst  $$(MAKEFILE_DIR)/downloads/%, third_party/%,  $$(THIRD_PARTY_CC_SRCS)))
535
536# Get generated project includes from the includes with update path to third_party
537GENERATED_PROJECT_INCLUDES += $$(filter -I$$(MAKEFILE_DIR)/downloads/%, $$(INCLUDES))
538GENERATED_PROJECT_INCLUDES := $$(patsubst  -I$$(MAKEFILE_DIR)/downloads/%, -Ithird_party/%,  $$(GENERATED_PROJECT_INCLUDES))
539GENERATED_PROJECT_INCLUDES += $$(filter -isystem$$(MAKEFILE_DIR)/downloads/%, $$(INCLUDES))
540GENERATED_PROJECT_INCLUDES := $$(sort $$(patsubst  -isystem$$(MAKEFILE_DIR)/downloads/%, -isystemthird_party/%,  $$(GENERATED_PROJECT_INCLUDES)))
541
542# We dont copy the libraries, we just want to make sure we link to them correctly.
543MICROLITE_LIBS :=  $$(sort $$(patsubst  $$(MAKEFILE_DIR)/downloads/%, $$(TENSORFLOW_ROOT)$$(MAKEFILE_DIR)/downloads/%, $$(MICROLITE_LIBS)))
544LDFLAGS :=   $$(sort $$(patsubst  $$(MAKEFILE_DIR)/downloads/%, $$(TENSORFLOW_ROOT)$$(MAKEFILE_DIR)/downloads/%, $$(LDFLAGS)))
545
546# Copy all third party headers that are mentioned in includes
547THIRD_PARTY_CC_HDRS += $$(filter $$(MAKEFILE_DIR)/downloads/%, $$(MICROLITE_CC_HDRS))
548MICROLITE_CC_HDRS:= $$(sort $$(filter-out $$(THIRD_PARTY_CC_HDRS), $$(MICROLITE_CC_HDRS)))
549THIRD_PARTY_CC_HDRS :=  $$(sort $$(patsubst  $$(MAKEFILE_DIR)/downloads/%, third_party/%,  $$(THIRD_PARTY_CC_HDRS)))
550
551# Copy all third party headers that are mentioned in includes
552INCLUDE_HDRS := $$(wildcard $$(addsuffix /*.h,$$(filter $$(MAKEFILE_DIR)/downloads/%, $$(patsubst -I%,%,$$(INCLUDES)))))
553INCLUDE_HDRS += $$(wildcard $$(addsuffix /*.h,$$(filter $$(MAKEFILE_DIR)/downloads/%,  $$(patsubst -isystem%,%,$$(INCLUDES)))))
554INCLUDE_HDRS :=  $$(sort $$(INCLUDE_HDRS))
555THIRD_PARTY_CC_HDRS += $ $$(sort $(patsubst  $$(MAKEFILE_DIR)/downloads/%, third_party/%,  $$(INCLUDE_HDRS)))
556endif
557
558endef
559