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 191define generate_ceva_sp500_project 192ifeq ($(TARGET), ceva) 193ifeq ($(TARGET_ARCH), CEVA_SP500) 194 195$(PRJDIR)$(3)/$(1)/Makefile: tensorflow/lite/micro/tools/make/templates/ceva_SP500/ceva_app_makefile.tpl 196 @mkdir -p $$(dir $$@) 197 @sed -E 's#\%\{SRCS\}\%#$(4)#g' $$< | \ 198 sed -E 's#\%\{CC\}\%#$(CC_TOOL)#g' | \ 199 sed -E 's#\%\{CXX\}\%#$(CXX_TOOL)#g' | \ 200 sed -E 's#\%\{LD\}\%#$(LD_TOOL)#g' | \ 201 sed -E 's#\%\{EXECUTABLE\}\%#$(3).elf#g' | \ 202 sed -E 's#\%\{LD_FLAGS\}\%#$(6)#g' | \ 203 sed -E 's#\%\{CXX_FLAGS\}\%#$(7)#g' | \ 204 sed -E 's#\%\{CC_FLAGS\}\%#$(8)#g' | \ 205 sed -E 's#\%\{EXTRA_APP_SETTINGS\}\%#$(ARC_EXTRA_APP_SETTINGS)#g' | \ 206 sed -E 's#\%\{EXTRA_APP_RULES\}\%#$(ARC_EXTRA_APP_RULES)#g' | \ 207 sed -E 's#\%\{BIN_DEPEND\}\%#$(ARC_BIN_DEPEND)#g' | \ 208 sed -E 's#\%\{BIN_RULE\}\%#$(ARC_BIN_RULE)#g' | \ 209 sed -E 's#\%\{EXTRA_RM_TARGETS\}\%#$(ARC_EXTRA_RM_TARGETS)#g' | \ 210 sed -E 's#\%\{APP_RUN_CMD\}\%#$(ARC_APP_RUN_CMD)#g' | \ 211 sed -E 's#\%\{APP_DEBUG_CMD\}\%#$(ARC_APP_DEBUG_CMD)#g' | \ 212 sed -E 's#\%\{EXTRA_EXECUTE_RULES\}\%#$(ARC_EXTRA_EXECUTE_RULES)#g' > $$@ 213 214$(PRJDIR)$(3)/$(1)/%: tensorflow/lite/micro/tools/make/templates/ceva_SP500/%.tpl 215 @cp $$< $$@ 216 217$(foreach var,$(CEVA_TARGET_FILES_DIRS),$(eval $(call path_changing_copy_file,$(PRJDIR)$(3)/$(1),$(var)))) 218 219endif 220endif 221endef 222 223 224 225 226 227# Creates a set of rules to build a standalone Arduino project for an 228# executable, including all of the source and header files required in a 229# separate folder and a simple makefile. 230# Arguments are: 231# 1 - Project file template names. 232# 2 - Name of executable. 233# 3 - List of C/C++ source files needed to build the target. 234# 4 - List of C/C++ header files needed to build the target. 235# 5 - Linker flags required. 236# 6 - C++ compilation flags needed. 237# 7 - C compilation flags needed. 238# Calling eval on the output will create a <Name>_makefile target that you 239# can invoke to create the standalone project. 240define generate_arduino_project 241 242$(PRJDIR)$(2)/arduino/examples/%.c: tensorflow/lite/micro/examples/%.c 243 @mkdir -p $$(dir $$@) 244 @python tensorflow/lite/micro/tools/make/transform_source.py \ 245 --platform=arduino \ 246 --is_example_source \ 247 --source_path="$$<" \ 248 --third_party_headers="$(4)" < $$< > $$@ 249 250$(PRJDIR)$(2)/arduino/examples/%.cpp: tensorflow/lite/micro/examples/%.cc 251 @mkdir -p $$(dir $$@) 252 @python tensorflow/lite/micro/tools/make/transform_source.py \ 253 --platform=arduino \ 254 --is_example_source \ 255 --source_path="$$<" \ 256 --third_party_headers="$(4)" < $$< > $$@ 257 258$(PRJDIR)$(2)/arduino/examples/%.h: tensorflow/lite/micro/examples/%.h 259 @mkdir -p $$(dir $$@) 260 @python tensorflow/lite/micro/tools/make/transform_source.py \ 261 --platform=arduino \ 262 --is_example_source \ 263 --source_path="$$<" \ 264 --third_party_headers="$(4)" < $$< > $$@ 265 266$(PRJDIR)$(2)/arduino/examples/%/main.ino: tensorflow/lite/micro/examples/%/main_functions.cc 267 @mkdir -p $$(dir $$@) 268 @python tensorflow/lite/micro/tools/make/transform_source.py \ 269 --platform=arduino \ 270 --is_example_ino \ 271 --source_path="$$<" \ 272 --third_party_headers="$(4)" < $$< > $$@ 273 274$(PRJDIR)$(2)/arduino/src/%.cpp: %.cc 275 @mkdir -p $$(dir $$@) 276 @python tensorflow/lite/micro/tools/make/transform_source.py \ 277 --platform=arduino \ 278 --third_party_headers="$(4)" < $$< > $$@ 279 280$(PRJDIR)$(2)/arduino/src/%.h: %.h third_party_downloads 281 @mkdir -p $$(dir $$@) 282 @python tensorflow/lite/micro/tools/make/transform_source.py \ 283 --platform=arduino \ 284 --third_party_headers="$(4)" < $$< > $$@ 285 286$(PRJDIR)$(2)/arduino/LICENSE: LICENSE 287 @mkdir -p $$(dir $$@) 288 @cp $$< $$@ 289 290$(PRJDIR)$(2)/arduino/src/%: % third_party_downloads 291 @mkdir -p $$(dir $$@) 292 @python tensorflow/lite/micro/tools/make/transform_source.py \ 293 --platform=arduino \ 294 --third_party_headers="$(4)" < $$< > $$@ 295 296$(PRJDIR)$(2)/arduino/src/third_party/%: tensorflow/lite/micro/tools/make/downloads/% third_party_downloads 297 @mkdir -p $$(dir $$@) 298 @python tensorflow/lite/micro/tools/make/transform_source.py \ 299 --platform=arduino \ 300 --third_party_headers="$(4)" < $$< > $$@ 301 302$(PRJDIR)$(2)/arduino/src/third_party/%.cpp: tensorflow/lite/micro/tools/make/downloads/%.cc third_party_downloads 303 @mkdir -p $$(dir $$@) 304 @python tensorflow/lite/micro/tools/make/transform_source.py \ 305 --platform=arduino \ 306 --third_party_headers="$(4)" < $$< > $$@ 307 308$(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 309 @mkdir -p $$(dir $$@) 310 @python tensorflow/lite/micro/tools/make/transform_source.py \ 311 --platform=arduino \ 312 --third_party_headers="$(4)" < $$< | \ 313 sed -E 's/utility\.h/utility/g' > $$@ 314 315$(PRJDIR)$(2)/arduino/src/third_party/kissfft/kiss_fft.h: tensorflow/lite/micro/tools/make/downloads/kissfft/kiss_fft.h third_party_downloads 316 @mkdir -p $$(dir $$@) 317 @python tensorflow/lite/micro/tools/make/transform_source.py \ 318 --platform=arduino \ 319 --third_party_headers="$(4)" < $$< | \ 320 sed -E 's@#include <string.h>@//#include <string.h> /* Patched by helper_functions.inc for Arduino compatibility */@g' > $$@ 321 322$(PRJDIR)$(2)/arduino/%: tensorflow/lite/micro/tools/make/templates/% 323 @mkdir -p $$(dir $$@) 324 @sed -E 's#\%\{SRCS\}\%#$(3)#g' $$< | \ 325 sed -E 's#\%\{EXECUTABLE\}\%#$(2)#g' | \ 326 sed -E 's#\%\{LINKER_FLAGS\}\%#$(5)#g' | \ 327 sed -E 's#\%\{CXX_FLAGS\}\%#$(6)#g' | \ 328 sed -E 's#\%\{CC_FLAGS\}\%#$(7)#g' > $$@ 329 330$(PRJDIR)$(2)/arduino/examples/$(2)/$(2).ino: tensorflow/lite/micro/tools/make/templates/arduino_example.ino 331 @mkdir -p $$(dir $$@) 332 @cp $$< $$@ 333 334$(PRJDIR)$(2)/arduino/src/TensorFlowLite.h: tensorflow/lite/micro/tools/make/templates/TensorFlowLite.h 335 @mkdir -p $$(dir $$@) 336 @cp $$< $$@ 337 338# This would be cleaner if we broke up the list of dependencies into variables, 339# but these get hard to define with the evaluation approach used to define make 340# functions. 341generate_$(2)_arduino_project: \ 342$(addprefix $(PRJDIR)$(2)/arduino/, \ 343$(patsubst tensorflow/%,src/tensorflow/%,\ 344$(patsubst examples/%/main_functions.cpp,examples/%/main.ino,\ 345$(patsubst examples/%_test.cpp,examples/%_test.ino,\ 346$(patsubst tensorflow/lite/micro/examples/%,examples/%,\ 347$(patsubst third_party/%,src/third_party/%,\ 348$(patsubst %.cc,%.cpp,$(3)))))))) \ 349$(addprefix $(PRJDIR)$(2)/arduino/, \ 350$(patsubst tensorflow/%,src/tensorflow/%,\ 351$(patsubst tensorflow/lite/micro/examples/%,examples/%,\ 352$(patsubst third_party/%,src/third_party/%,$(4))))) \ 353$(addprefix $(PRJDIR)$(2)/arduino/,$(1)) \ 354$(PRJDIR)$(2)/arduino/src/TensorFlowLite.h 355 356generate_$(2)_arduino_library_zip: generate_$(2)_arduino_project 357 cp -r $(PRJDIR)$(2)/arduino $(PRJDIR)$(2)/tensorflow_lite 358 python tensorflow/lite/micro/tools/make/fix_arduino_subfolders.py $(PRJDIR)$(2)/tensorflow_lite 359 @cd $(PRJDIR)$(2) && zip -q -r tensorflow_lite.zip tensorflow_lite 360 361ALL_PROJECT_TARGETS += $(if $(findstring _test,$(2)),,generate_$(2)_arduino_library_zip) 362 363 ARDUINO_LIBRARY_ZIPS += $(if $(findstring _mock,$(2)),,$(if $(findstring _test,$(2)),,$(PRJDIR)$(2)/tensorflow_lite.zip)) 364 365endef 366 367# Creates a set of rules to build a standalone ESP-IDF project for an 368# executable, including all of the source and header files required in a 369# separate folder. 370# Arguments are: 371# 1 - Project file template names. 372# 2 - Name of executable. 373# 3 - List of C/C++ source files needed to build the TF Micro component. 374# 4 - List of C/C++ header files needed to build the TF Micro component. 375# 5 - List of C/C++ source files needed to build this particular project. 376# 6 - List of C/C++ header files needed to build this particular project. 377# 7 - Linker flags required. 378# 8 - C++ compilation flags needed. 379# 9 - C compilation flags needed. 380# 10 - List of includes. 381define generate_esp_project 382$(PRJDIR)$(2)/esp-idf/LICENSE: LICENSE 383 @mkdir -p $$(dir $$@) 384 @cp $$< $$@ 385 386$(PRJDIR)$(2)/esp-idf/%: tensorflow/lite/micro/examples/$(2)/esp/% 387 @mkdir -p $$(dir $$@) 388 @cp $$< $$@ 389 390$(PRJDIR)$(2)/esp-idf/main/%.cc: tensorflow/lite/micro/examples/$(2)/%.cc 391 @mkdir -p $$(dir $$@) 392 @python tensorflow/lite/micro/tools/make/transform_source.py \ 393 --platform=esp \ 394 --is_example_source \ 395 --source_path="$$<" \ 396 < $$< > $$@ 397 398$(PRJDIR)$(2)/esp-idf/main/%.h: tensorflow/lite/micro/examples/$(2)/%.h 399 @mkdir -p $$(dir $$@) 400 @python tensorflow/lite/micro/tools/make/transform_source.py \ 401 --platform=esp \ 402 --is_example_source \ 403 --source_path="$$<" \ 404 < $$< > $$@ 405 406$(PRJDIR)$(2)/esp-idf/main/%: tensorflow/lite/micro/examples/$(2)/% 407 @mkdir -p $$(dir $$@) 408 @cp $$< $$@ 409 410$(PRJDIR)$(2)/esp-idf/components/tfmicro/%: % third_party_downloads 411 @mkdir -p $$(dir $$@) 412 @cp $$< $$@ 413 414$(PRJDIR)$(2)/esp-idf/components/tfmicro/third_party/%: tensorflow/lite/micro/tools/make/downloads/% third_party_downloads 415 @mkdir -p $$(dir $$@) 416 @cp $$< $$@ 417 418$(PRJDIR)$(2)/esp-idf/sdkconfig.defaults: tensorflow/lite/micro/examples/$(2)/esp/sdkconfig.defaults 419 @mkdir -p $$(dir $$@) 420 @cp $$< $$@ 421 422$(PRJDIR)$(2)/esp-idf/%: tensorflow/lite/micro/tools/make/templates/esp/%.tpl 423# Split the sources into 2 components: 424# - Main component contains only the example's sources, relative from its dir. 425# - TFL Micro component contains everything but the example sources. 426 $(eval MAIN_SRCS := $(filter tensorflow/lite/micro/examples/%,$(5))) 427 $(eval MAIN_SRCS_RELATIVE := $(patsubst tensorflow/lite/micro/examples/$(2)/%,%,$(MAIN_SRCS))) 428 $(eval TFLM_SRCS := $(filter-out tensorflow/lite/micro/examples/%,$(5)) $(3)) 429 430 @mkdir -p $$(dir $$@) 431 @sed -E 's#\%\{COMPONENT_SRCS\}\%#$(TFLM_SRCS)#g' $$< | \ 432 sed -E 's#\%\{MAIN_SRCS\}\%#$(MAIN_SRCS_RELATIVE)#g' | \ 433 sed -E 's#\%\{EXECUTABLE\}\%#$(2)#g' | \ 434 sed -E 's#\%\{COMPONENT_INCLUDES\}\%#$(10)#g' | \ 435 sed -E 's#\%\{LINKER_FLAGS\}\%#$(7)#g' | \ 436 sed -E 's#\%\{CXX_FLAGS\}\%#$(8)#g' | \ 437 sed -E 's#\%\{CC_FLAGS\}\%#$(9)#g' > $$@ 438 439generate_$(2)_esp_project: \ 440$(addprefix $(PRJDIR)$(2)/esp-idf/,\ 441$(patsubst tensorflow/%,components/tfmicro/tensorflow/%,\ 442$(patsubst third_party/%,components/tfmicro/third_party/%,\ 443$(patsubst tensorflow/lite/micro/examples/$(2)/%,main/%,$(3) $(4) $(5) $(6))))) \ 444$(addprefix $(PRJDIR)$(2)/esp-idf/,$(1)) 445 446ALL_PROJECT_TARGETS += generate_$(2)_esp_project 447endef 448 449# Specialized version of generate_project for TF Lite Micro test targets that 450# automatically includes standard library files, so you just need to pass the 451# test name and any extra source files required. 452# Arguments are: 453# 1 - Name of test. 454# 2 - C/C++ source files implementing the test. 455# 3 - C/C++ header files needed for the test. 456# Calling eval on the output will create targets that you can invoke to 457# generate the standalone project. 458define generate_microlite_projects 459$(call generate_project,make,$(MAKE_PROJECT_FILES) $($(1)_MAKE_PROJECT_FILES),$(1),$(MICROLITE_CC_SRCS) $(THIRD_PARTY_CC_SRCS) $(MICROLITE_CC_KERNEL_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)) 460$(call generate_arc_project,make,$(MAKE_PROJECT_FILES) $($(1)_MAKE_PROJECT_FILES),$(1),$(MICROLITE_CC_SRCS) $(THIRD_PARTY_CC_SRCS) $(MICROLITE_CC_KERNEL_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)) 461$(call generate_ceva_bx1_project,make,$(MAKE_PROJECT_FILES) $($(1)_MAKE_PROJECT_FILES),$(1),$(MICROLITE_CC_SRCS) $(THIRD_PARTY_CC_SRCS) $(MICROLITE_CC_KERNEL_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)) 462$(call generate_ceva_sp500_project,make,$(MAKE_PROJECT_FILES) $($(1)_MAKE_PROJECT_FILES),$(1),$(MICROLITE_CC_SRCS) $(THIRD_PARTY_CC_SRCS) $(MICROLITE_CC_KERNEL_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)) 463$(call generate_project,mbed,$(MBED_PROJECT_FILES) $($(1)_MBED_PROJECT_FILES),$(1),$(MICROLITE_CC_SRCS) $(THIRD_PARTY_CC_SRCS) $(MICROLITE_CC_KERNEL_SRCS) $(2),$(MICROLITE_CC_HDRS) $(THIRD_PARTY_CC_HDRS) $(MICROLITE_TEST_HDRS) $(3),$(MICROLITE_LIBS),$(CXXFLAGS),$(CCFLAGS),$(TARGET_TOOLCHAIN_ROOT),$(TARGET_TOOLCHAIN_PREFIX)) 464$(call generate_project,keil,$(KEIL_PROJECT_FILES) $($(1)_KEIL_PROJECT_FILES),$(1),$(MICROLITE_CC_SRCS) $(THIRD_PARTY_CC_SRCS) $(MICROLITE_CC_KERNEL_SRCS) $(2),$(MICROLITE_CC_HDRS) $(THIRD_PARTY_CC_HDRS) $(MICROLITE_TEST_HDRS) $(3),$(MICROLITE_LIBS),$(CXXFLAGS),$(CCFLAGS),$(TARGET_TOOLCHAIN_ROOT),$(TARGET_TOOLCHAIN_PREFIX)) 465ifeq (,$(findstring _benchmark,$(1))) 466 $(call generate_arduino_project,$(ARDUINO_PROJECT_FILES) $($(1)_ARDUINO_PROJECT_FILES),$(1),$(MICROLITE_CC_SRCS) $(THIRD_PARTY_CC_SRCS) $(MICROLITE_CC_KERNEL_SRCS) $(2),$(MICROLITE_CC_HDRS) $(THIRD_PARTY_CC_HDRS) $(MICROLITE_TEST_HDRS) $(3),$(MICROLITE_LIBS),$(CXXFLAGS),$(CCFLAGS)) 467endif 468$(call generate_esp_project,$(ESP_PROJECT_FILES) $($(1)_ESP_PROJECT_FILES),$(1),$(MICROLITE_CC_SRCS) $(THIRD_PARTY_CC_SRCS) $(MICROLITE_CC_KERNEL_SRCS),$(MICROLITE_CC_HDRS) $(THIRD_PARTY_CC_HDRS) $(MICROLITE_TEST_HDRS),$(2),$(3),$(MICROLITE_LIBS),$(CXXFLAGS),$(CCFLAGS),$(PROJECT_INCLUDES)) 469endef 470 471# Handles the details of generating a binary target, including specializing 472# for the current platform, and generating project file targets. 473# 474# Note that while the function is called microlite_test, it is used for both 475# test and non-test binaries. 476 477# Files that end with _test are added as test targets (i.e. can be executed with 478# make test_<target>. ALl others can be executed with make run_<target> 479# 480# Arguments are: 481# 1 - Name of target. 482# 2 - C/C++ source files 483# 3 - C/C++ header files 484# 4 - if "exclude", then the non-test target will be excluded from 485# MICROLITE_BUILD_TARGETS. This exception is needed because not all the 486# microlite_test targets (e.g. the examples) are buildable on all platforms. 487# Calling eval on the output will create the targets that you need. 488define microlite_test 489ifeq (,$(findstring _test, $(1))) 490 $(eval $(call generate_project_third_party_parsing)) 491endif 492 493$(1)_LOCAL_SRCS := $(2) 494$(1)_LOCAL_SRCS := $$(call specialize,$$($(1)_LOCAL_SRCS)) 495ALL_SRCS += $$($(1)_LOCAL_SRCS) 496$(1)_LOCAL_HDRS := $(3) 497$(1)_LOCAL_OBJS := $$(addprefix $$(CORE_OBJDIR), \ 498$$(patsubst %.S,%.o,$$(patsubst %.cc,%.o,$$(patsubst %.c,%.o,$$($(1)_LOCAL_SRCS))))) 499$(1)_BINARY := $$(BINDIR)$(1) 500$$($(1)_BINARY): $$($(1)_LOCAL_OBJS) $$(MICROLITE_LIB_PATH) 501 @mkdir -p $$(dir $$@) 502 $$(CXX) $$(CXXFLAGS) $$(INCLUDES) \ 503 -o $$($(1)_BINARY) $$($(1)_LOCAL_OBJS) \ 504 $$(MICROLITE_LIB_PATH) $$(LDFLAGS) $$(MICROLITE_LIBS) 505$(1): $$($(1)_BINARY) 506$(1)_bin: $$($(1)_BINARY).bin 507 508ifneq (,$(findstring _test,$(1))) 509 MICROLITE_TEST_TARGETS += test_$(1) 510 MICROLITE_BUILD_TARGETS += $$($(1)_BINARY) 511 512test_$(1): $$($(1)_BINARY) 513 $$(TEST_SCRIPT) $$($(1)_BINARY) $$(TEST_PASS_STRING) $$(TARGET) 514 515else 516 ifeq ($(findstring exclude,$(4)),) 517 MICROLITE_BUILD_TARGETS += $$($(1)_BINARY) 518 endif 519 520run_$(1): $$($(1)_BINARY) 521 $$(TEST_SCRIPT) $$($(1)_BINARY) non_test_binary $$(TARGET) 522endif 523 524$(eval $(call generate_microlite_projects,$(1),$(call specialize,$(2)),$(3))) 525endef 526 527# Adds a dependency for a third-party library that needs to be downloaded from 528# an external source. 529# Arguments are: 530# 1 - URL to download archive file from (can be .zip, .tgz, or .bz). 531# 2 - MD5 sum of archive, to check integrity. Use md5sum tool to generate. 532# 3 - Folder name to unpack library into, inside tf/l/x/m/t/downloads root. 533# 4 - Optional patching action, must match clause in download_and_extract.sh. 534# 5 - Optional patching action parameter 535# These arguments are packed into a single '!' separated string, so no element 536# can contain a '!'. 537define add_third_party_download 538THIRD_PARTY_DOWNLOADS += $(1)!$(2)!tensorflow/lite/micro/tools/make/downloads/$(3)!$(4)!$(5) 539endef 540 541# Unpacks an entry in a list of strings created by add_third_party_download, and 542# defines a dependency rule to download the library. The download_and_extract.sh 543# script is used to handle to downloading and unpacking. 544# 1 - Information about the library, separated by '!'s. 545define create_download_rule 546$(word 3, $(subst !, ,$(1))): 547 $(DOWNLOAD_SCRIPT) $(subst !, ,$(1)) 548THIRD_PARTY_TARGETS += $(word 3, $(subst !, ,$(1))) 549endef 550 551# Recursively find all files of given pattern 552# Arguments are: 553# 1 - Starting path 554# 2 - File pattern, e.g: *.h 555recursive_find = $(wildcard $(1)$(2)) $(foreach dir,$(wildcard $(1)*),$(call recursive_find,$(dir)/,$(2))) 556 557 558# Modifies the Makefile to include all third party Srcs so that generate 559# projects will create a Makefile that can be immediatley compiled without 560# modification 561define generate_project_third_party_parsing 562 563ifeq ($$(PARSE_THIRD_PARTY), true) 564# Get generated src includes with update path to third party 565THIRD_PARTY_CC_SRCS += $$(filter $$(MAKEFILE_DIR)/downloads/%, $$(MICROLITE_CC_SRCS)) 566MICROLITE_CC_SRCS := $$(filter-out $$(THIRD_PARTY_CC_SRCS), $$(MICROLITE_CC_SRCS)) 567THIRD_PARTY_CC_SRCS := $$(sort $$(patsubst $$(MAKEFILE_DIR)/downloads/%, third_party/%, $$(THIRD_PARTY_CC_SRCS))) 568 569# Get generated project includes from the includes with update path to third_party 570GENERATED_PROJECT_INCLUDES += $$(filter -I$$(MAKEFILE_DIR)/downloads/%, $$(INCLUDES)) 571GENERATED_PROJECT_INCLUDES := $$(patsubst -I$$(MAKEFILE_DIR)/downloads/%, -Ithird_party/%, $$(GENERATED_PROJECT_INCLUDES)) 572GENERATED_PROJECT_INCLUDES += $$(filter -isystem$$(MAKEFILE_DIR)/downloads/%, $$(INCLUDES)) 573GENERATED_PROJECT_INCLUDES := $$(sort $$(patsubst -isystem$$(MAKEFILE_DIR)/downloads/%, -isystemthird_party/%, $$(GENERATED_PROJECT_INCLUDES))) 574 575# We dont copy the libraries, we just want to make sure we link to them correctly. 576MICROLITE_LIBS := $$(sort $$(patsubst $$(MAKEFILE_DIR)/downloads/%, $$(TENSORFLOW_ROOT)$$(MAKEFILE_DIR)/downloads/%, $$(MICROLITE_LIBS))) 577LDFLAGS := $$(sort $$(patsubst $$(MAKEFILE_DIR)/downloads/%, $$(TENSORFLOW_ROOT)$$(MAKEFILE_DIR)/downloads/%, $$(LDFLAGS))) 578 579# Copy all third party headers that are mentioned in includes 580THIRD_PARTY_CC_HDRS += $$(filter $$(MAKEFILE_DIR)/downloads/%, $$(MICROLITE_CC_HDRS)) 581MICROLITE_CC_HDRS:= $$(sort $$(filter-out $$(THIRD_PARTY_CC_HDRS), $$(MICROLITE_CC_HDRS))) 582THIRD_PARTY_CC_HDRS := $$(sort $$(patsubst $$(MAKEFILE_DIR)/downloads/%, third_party/%, $$(THIRD_PARTY_CC_HDRS))) 583 584# Copy all third party headers that are mentioned in includes 585INCLUDE_HDRS := $$(wildcard $$(addsuffix /*.h,$$(filter $$(MAKEFILE_DIR)/downloads/%, $$(patsubst -I%,%,$$(INCLUDES))))) 586INCLUDE_HDRS += $$(wildcard $$(addsuffix /*.h,$$(filter $$(MAKEFILE_DIR)/downloads/%, $$(patsubst -isystem%,%,$$(INCLUDES))))) 587INCLUDE_HDRS := $$(sort $$(INCLUDE_HDRS)) 588THIRD_PARTY_CC_HDRS += $ $$(sort $(patsubst $$(MAKEFILE_DIR)/downloads/%, third_party/%, $$(INCLUDE_HDRS))) 589endif 590 591endef 592