-
Notifications
You must be signed in to change notification settings - Fork 0
/
Meta.mk
740 lines (572 loc) · 21.1 KB
/
Meta.mk
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
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
# Copyright (c) 2015 Bradley Kim Schleusner < [email protected] >
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
# --------------------------------------------------------------- DOCUMENTATION
# See README.md for documentation, or the github project page
# https://github.com/bradschl/metamake
# ------------------------------------------------------------- MAKEFILE TWEAKS
# Disable implicit rules
.SUFFIXES:
# Enable secondary expansion for recipe dependency variables that may not
# be defined at the time that the meta rules are expanded
.SECONDEXPANSION:
# ------------------------------------------------------------------ VERSIONING
# API breaking version
METAMAKE_MAJOR_VERSION := 4
# Bug fix version within the API
METAMAKE_MINOR_VERSION := 0
# ------------------------------------------------------------ BUILD CONSTRUCTS
# $(1) - Architecture - variable name
# $(2) - Build directory
BEGIN_DEFINE_ARCH = $(eval $(call EVAL_BEGIN_DEFINE_ARCH,$(strip $(1)),$(strip $(2))))
END_DEFINE_ARCH = $(eval $(call EVAL_END_DEFINE_ARCH))
# $(1) - Architecture - variable name
BEGIN_APPEND_ARCH_FLAGS = $(eval $(call EVAL_BEGIN_APPEND_ARCH_FLAGS,$(strip $(1))))
END_APPEND_ARCH_FLAGS = $(eval $(call EVAL_END_APPEND_ARCH_FLAGS))
# $(1) - Architecture - variable name
BEGIN_ARCH_BUILD = $(eval $(call EVAL_BEGIN_ARCH_BUILD,$(strip $(1))))
END_ARCH_BUILD = $(eval $(EVAL_END_ARCH_BUILD))
BEGIN_UNIVERSAL_BUILD = $(eval $(EVAL_BEGIN_UNIVERSAL_BUILD))
END_UNIVERSAL_BUILD = $(eval $(EVAL_END_UNIVERSAL_BUILD))
# $(1) - Flags
ADD_AS_INCLUDE = \
$(eval BUILD_CMD_ := $$(value BUILD_CMD_) \
$$$$(eval $$$$(call EVAL_ADD_AS_INCLUDE,$$$$(strip $$(1)))))
# $(1) - Includes (paths)
ADD_C_INCLUDE = \
$(eval BUILD_CMD_ := $$(value BUILD_CMD_) \
$$$$(eval $$$$(call EVAL_ADD_C_INCLUDE,$$$$(strip $$(1)))))
# $(1) - Includes (paths)
ADD_CXX_INCLUDE = \
$(eval BUILD_CMD_ := $$(value BUILD_CMD_) \
$$$$(eval $$$$(call EVAL_ADD_CXX_INCLUDE,$$$$(strip $$(1)))))
# $(1) - Flags
ADD_ASF_FLAG = \
$(eval BUILD_CMD_ := $$(value BUILD_CMD_) \
$$$$(eval $$$$(call EVAL_ADD_ASF_FLAG,$$$$(strip $$(1)))))
# $(1) - Flags
ADD_CF_FLAG = \
$(eval BUILD_CMD_ := $$(value BUILD_CMD_) \
$$$$(eval $$$$(call EVAL_ADD_CF_FLAG,$$$$(strip $$(1)))))
# $(1) - Flags
ADD_CXXF_FLAG = \
$(eval BUILD_CMD_ := $$(value BUILD_CMD_) \
$$$$(eval $$$$(call EVAL_ADD_CXXF_FLAG,$$$$(strip $$(1)))))
# $(1) - Flags
ADD_LF_FLAG = \
$(eval BUILD_CMD_ := $$(value BUILD_CMD_) \
$$$$(eval $$$$(call EVAL_ADD_LF_FLAG,$$$$(strip $$(1)))))
# $(1) - Flags
ADD_LL_FLAG = \
$(eval BUILD_CMD_ := $$(value BUILD_CMD_) \
$$$$(eval $$$$(call EVAL_ADD_LL_FLAG,$$$$(strip $$(1)))))
# $(1) - Custom build step dependencies
ADD_CUSTOM_BUILD_DEP = \
$(eval BUILD_CMD_ := $$(value BUILD_CMD_) \
$$$$(eval $$$$(call EVAL_ADD_CUSTOM_BUILD_DEP,$$$$(strip $$(1)))))
# $(1) - Custom link step dependencies
ADD_CUSTOM_LINK_DEP = \
$(eval BUILD_CMD_ := $$(value BUILD_CMD_) \
$$$$(eval $$$$(call EVAL_ADD_CUSTOM_LINK_DEP,$$$$(strip $$(1)))))
# $(1) - Source files, .c .cpp .cc .S
BUILD_SOURCE = \
$(eval BUILD_CMD_ := $$(value BUILD_CMD_) \
$$(call CALL_PUSH_LOCAL_PARAMS_) \
$$$$(eval $$$$(call EVAL_BUILD_SOURCE,$$$$(strip $$(1)))))
# $(1) - Output executable name
CXX_LINK = \
$(eval BUILD_CMD_ := $$(value BUILD_CMD_) \
$$(call CALL_PUSH_LOCAL_PARAMS_) \
$$$$(eval $$$$(call EVAL_CXX_LINK_RULE,$$$$(strip $$(1)))))
# $(1) - Output executable name
CC_LINK = \
$(eval BUILD_CMD_ := $$(value BUILD_CMD_) \
$$(call CALL_PUSH_LOCAL_PARAMS_) \
$$$$(eval $$$$(call EVAL_C_LINK_RULE,$$$$(strip $$(1)))))
# $(1) - Library base name
MAKE_LIBRARY = \
$(eval BUILD_CMD_ := $$(value BUILD_CMD_) \
$$$$(eval $$$$(call EVAL_AR_RULE,$$$$(strip $$(1)),$$$$(call LIBNAME_TO_LIBA,$$(1)))))
# $(1) - Dependency friendly names
IMPORT_DEPS = \
$(eval BUILD_CMD_ := $$(value BUILD_CMD_) \
$$$$(eval $$$$(call EVAL_IMPORT_DEPS,$$$$(strip $$(1)))))
# Export build targets to the 'all' target
APPEND_ALL_TARGET_VAR = \
$(eval BUILD_CMD_ := $$(value BUILD_CMD_) \
$$$$(eval ALL_TARGETS := $$$$(ALL_TARGETS) $$$$(LAST_TARGET_)))
# $(1) - Friendly dependency name
EXPORT_SHALLOW_DEPS = \
$(eval BUILD_CMD_ := $$(value BUILD_CMD_) \
$$$$(eval $$$$(call EVAL_EXPORT_SHALLOW_DEPS,$$$$(strip $$(1))))) \
$(eval PRE_EXPORT_LIST_ := $$(value PRE_EXPORT_LIST_) $$(1))
# $(1) - Variable name
APPEND_TARGET_TO_VAR = \
$(eval BUILD_CMD_ := $$(value BUILD_CMD_) \
$$$$(eval $$$$(strip $$(1)) := $$$$($$(strip $$(1))) $$$$(LAST_TARGET_)))
# ----------------------------------------------------------------- OTHER TOOLS
# $(1) - Architecture name
GET_ARCH_PREFIX = $(strip \
$(eval $(call EVAL_ASSERT_ARCH,$(strip $(1)))) \
$($(strip $(1))_PREFIX))
# (1) - Directory to search
FIND_SOURCE_IN_DIR = $(shell find $(strip $(1)) -name "*.cpp" -or -name "*.cc" -or -name "*.c" -or -name "*.S" -or -name "*.s")
# --------------------------------------------------------- INTERNAL META RULES
# $(1) - Source files
C_SRC_TO_OBJ = $(strip $(patsubst %.c,$(OBJ_DIR)/%.o,$(1)))
CPP_SRC_TO_OBJ = $(strip $(patsubst %.cpp,$(OBJ_DIR)/%.o,$(1)))
CC_SRC_TO_OBJ = $(strip $(patsubst %.cc,$(OBJ_DIR)/%.o,$(1)))
ASM_S_SRC_TO_OBJ = $(strip $(patsubst %.S,$(OBJ_DIR)/%.o,$(1)))
ASM_s_SRC_TO_OBJ = $(strip $(patsubst %.s,$(OBJ_DIR)/%.o,$(1)))
# $(1) - library base name
LIBNAME_TO_LIBA = $(strip $(LIB_DIR)/lib$(strip $(1)).a)
# In-recipe rule
MAKE_DIRECTORY = @mkdir -p $(@D)
# (none)
CALL_PUSH_LOCAL_PARAMS_ = $$(eval ASF := $(ASF)) \
$$(eval CF := $(CF)) \
$$(eval CXXF := $(CXXF)) \
$$(eval LF := $(LF)) \
$$(eval LL := $(LL))
# (none)
define EVAL_CLEAR_LOCAL_PARAMS
ASF :=
CF :=
CXXF :=
LF :=
LL :=
endef
# $(1) - Architecture name
# $(2) - Build directory
define EVAL_BEGIN_DEFINE_ARCH
ifeq ($(1),)
$$(error Architecture name not defined)
endif
ifeq ($(2),)
$$(error Architecture build directory not defined)
endif
ifneq ($$(filter $(1), $$(ALL_ARCH_LIST_)),)
$$(error Architecture has already been defined)
endif
ARCH_ := $(1)
BUILD_DIR_ := $(2)
PREFIX :=
$$(eval $$(EVAL_CLEAR_LOCAL_PARAMS))
$$(eval $$(call EVAL_CLEAN_RULE,$(2)))
endef
# (none)
define EVAL_END_DEFINE_ARCH
$(ARCH_)_PREFIX := $(PREFIX)
$(ARCH_)ASF := $($(ARCH_)ASF) $(ASF)
$(ARCH_)CF := $($(ARCH_)CF) $(CF)
$(ARCH_)CXXF := $($(ARCH_)CXXF) $(CXXF)
$(ARCH_)LF := $($(ARCH_)LF) $(LF)
$(ARCH_)LL := $($(ARCH_)LL) $(LL)
$(ARCH_)_BUILD_DIR := $(BUILD_DIR_)
ALL_ARCH_LIST_ := $$(ALL_ARCH_LIST_) $(ARCH_)
ARCH_ :=
BUILD_DIR_ :=
PREFIX :=
$$(eval $$(EVAL_CLEAR_LOCAL_PARAMS))
endef
# $(1) - Arch name
define EVAL_BEGIN_ARCH_BUILD
ifeq ($(1),)
$$(error Missing architecture name)
endif
ifeq ($$(filter $(1), $$(ALL_ARCH_LIST_)),)
$$(error Architecture has not been defined yet)
endif
AS := $$($(1)_PREFIX)as
AR := $$($(1)_PREFIX)ar
CC := $$($(1)_PREFIX)gcc
CXX := $$($(1)_PREFIX)g++
LD := $$($(1)_PREFIX)ld
NM := $$($(1)_PREFIX)nm
STRIP := $$($(1)_PREFIX)strip
OBJCOPY := $$($(1)_PREFIX)objcopy
OBJDUMP := $$($(1)_PREFIX)objdump
# Artifact parths
BUILD_DIR := $$($(1)_BUILD_DIR)
# Note: These used to be separate paths, they still can be
OBJ_DIR := $$($(1)_BUILD_DIR)/obj
LIB_DIR := $$($(1)_BUILD_DIR)/lib
BIN_DIR := $$($(1)_BUILD_DIR)/bin
ARCH := $(1)
OBJS :=
LIBS_BASENAME :=
LAST_TARGET_ :=
# Locally created dependencies
LDEP_ASF_ :=
LDEP_CF_ :=
LDEP_CXXF_ :=
LDEP_LF_ :=
LDEP_LL_ :=
LDEP_ASIF_ :=
LDEP_CIF_ :=
LDEP_CXXIF_ :=
LDEP_LINK_ :=
# Local (hidden) flags
$$(eval $$(EVAL_CLEAR_LOCAL_PARAMS))
# Imported dependencies
DEPS_ASF_ :=
DEPS_CF_ :=
DEPS_CXXF_ :=
DEPS_LF_ :=
DEPS_LL_ :=
DEPS_ASIF_ :=
DEPS_CIF_ :=
DEPS_CXXIF_ :=
DEPS_LINK_ :=
DEPS_BUILD_ :=
# Post-expansion rules
PRE_EXPORT_LIST_ :=
BUILD_CMD_ :=
endef
define EVAL_END_ARCH_BUILD
# Expand the meta rules
$$(eval $$(BUILD_CMD_))
AS := false
AR := false
CC := false
CXX := false
LD := false
NM := false
STRIP := false
OBJCOPY := false
OBJDUMP := false
BUILD_DIR :=
OBJ_DIR :=
LIB_DIR :=
BIN_DIR :=
ARCH :=
OBJS :=
LIBS_BASENAME :=
LAST_TARGET_ :=
# Locally created dependencies
LDEP_ASF_ :=
LDEP_CF_ :=
LDEP_CXXF_ :=
LDEP_LF_ :=
LDEP_LL_ :=
LDEP_ASIF_ :=
LDEP_CIF_ :=
LDEP_CXXIF_ :=
LDEP_LINK_ :=
# Local (hidden) flags
$$(eval $$(EVAL_CLEAR_LOCAL_PARAMS))
# Imported dependencies
DEPS_ASF_ :=
DEPS_CF_ :=
DEPS_CXXF_ :=
DEPS_LF_ :=
DEPS_LL_ :=
DEPS_ASIF_ :=
DEPS_CIF_ :=
DEPS_CXXIF_ :=
DEPS_LINK_ :=
DEPS_BUILD_ :=
# Post-expansion rules
PRE_EXPORT_LIST_ :=
BUILD_CMD_ :=
endef
define EVAL_BEGIN_UNIVERSAL_BUILD
# Local build rule
PRE_EXPORT_LIST_ :=
BUILD_CMD_ :=
# Local (hidden) flags
$$(eval $$(EVAL_CLEAR_LOCAL_PARAMS))
endef
define EVAL_END_UNIVERSAL_BUILD
# Universal build rules
UNIV_BUILD_CMD_ := $$(value BUILD_CMD_)
UNIV_PRE_EXPORT_LIST_ := $$(value PRE_EXPORT_LIST_)
# Expand the universal rule for each known architecture
$$(foreach arch,$$(ALL_ARCH_LIST_),$$(eval $$(call EVAL_EXPAND_UNIV_DEPS,$$(arch))))
UNIV_BUILD_CMD_ :=
UNIV_PRE_EXPORT_LIST_ :=
# Local build rule
PRE_EXPORT_LIST_ :=
BUILD_CMD_ :=
# Local (hidden) flags
$$(eval $$(EVAL_CLEAR_LOCAL_PARAMS))
endef
# $(1) - Arch name
define EVAL_EXPAND_UNIV_DEPS
$$(foreach dep,$$(UNIV_PRE_EXPORT_LIST_),$$(eval $$(call EVAL_EXPAND_UNIV_DEP,$(1),$$(dep))))
endef
# $(1) - Arch name
# $(2) - Dep name
define EVAL_EXPAND_UNIV_DEP
# Only expand the rule if the dep has not already been exported
ifeq ($$(filter $(1)_$(2),$$(EXPORTED_DEP_NAMES_)),)
$$(call BEGIN_ARCH_BUILD, $(1))
$$(eval $$(UNIV_BUILD_CMD_))
$$(call END_ARCH_BUILD)
endif
endef
# $(1) - Object to clean
define EVAL_CLEAN_RULE
CLEAN_TARGETS := $$(CLEAN_TARGETS) $(1)_CLEAN
.PHONY: $(1)_CLEAN
$(1)_CLEAN:
$$(Q)rm -rf $(1)
endef
# $(1) - Source files
define EVAL_BUILD_SOURCE
LAST_TARGET_ :=
_SRC_ := $$(filter %.c,$(1))
ifneq ($$(_SRC_),)
$$(foreach f,$$(_SRC_),$$(eval $$(call EVAL_C_RULE,$$(f),$$(call C_SRC_TO_OBJ,$$(f)))))
endif
_SRC_ := $$(filter %.cpp,$(1))
ifneq ($$(_SRC_),)
$$(foreach f,$$(_SRC_),$$(eval $$(call EVAL_CXX_RULE,$$(f),$$(call CPP_SRC_TO_OBJ,$$(f)))))
endif
_SRC_ := $$(filter %.cc,$(1))
ifneq ($$(_SRC_),)
$$(foreach f,$$(_SRC_),$$(eval $$(call EVAL_CXX_RULE,$$(f),$$(call CC_SRC_TO_OBJ,$$(f)))))
endif
_SRC_ := $$(filter %.S,$(1))
ifneq ($$(_SRC_),)
$$(foreach f,$$(_SRC_),$$(eval $$(call EVAL_ASM_RULE,$$(f),$$(call ASM_S_SRC_TO_OBJ,$$(f)))))
endif
_SRC_ := $$(filter %.s,$(1))
ifneq ($$(_SRC_),)
$$(foreach f,$$(_SRC_),$$(eval $$(call EVAL_ASM_RULE,$$(f),$$(call ASM_s_SRC_TO_OBJ,$$(f)))))
endif
_SRC_ :=
endef
# $(1) - Output name
define EVAL_CXX_LINK_RULE
LAST_TARGET_ := $(BIN_DIR)/$(1)
$(BIN_DIR)/$(1)_CXX_LINK_CMD = \
$(CXX) \
$$($(ARCH)CXXF) $(CXXF) $(DEPS_CXXF_) $(LDEP_CXXF_) \
$$($(ARCH)LF) $(LF) $(DEPS_LF_) $(LDEP_LF_) \
-o $$@ $$(filter %.o,$$^) \
$$($(ARCH)LL) $(LL) $(DEPS_LL_) $(LDEP_LL_)
$(BIN_DIR)/$(1): $(OBJS) $$(value DEPS_LINK_) $$(value LDEP_LINK_)
$$(MAKE_DIRECTORY)
@echo "CXX LINK $$@"
$$(Q)$$($(BIN_DIR)/$(1)_CXX_LINK_CMD)
endef
# $(1) - Output name
define EVAL_C_LINK_RULE
LAST_TARGET_ := $(BIN_DIR)/$(1)
$(BIN_DIR)/$(1)_CC_LINK_CMD = \
$(CC) \
$$($(ARCH)CF) $(CF) $(DEPS_CF_) $(LDEP_CF_) \
$$($(ARCH)LF) $(LF) $(DEPS_LF_) $(LDEP_LF_) \
-o $$@ $$(filter %.o,$$^) \
$$($(ARCH)LL) $(LL) $(DEPS_LL_) $(LDEP_LL_)
$(BIN_DIR)/$(1): $(OBJS) $$(value DEPS_LINK_) $$(value LDEP_LINK_)
$$(MAKE_DIRECTORY)
@echo "CC LINK $$@"
$$(Q)$$($(BIN_DIR)/$(1)_CC_LINK_CMD)
endef
# (1) - Source filename
# (2) - Object filename
define EVAL_C_RULE
OBJS := $$(OBJS) $(2)
LAST_TARGET_ := $$(LAST_TARGET_) $(2)
$(2)_CC_CMD = \
$(CC) \
$$($(ARCH)CF) $(CF) $(DEPS_CF_) $(LDEP_CF_) \
$(LDEP_CIF_) $(DEPS_CIF_) \
-MMD -MP -MT '$(2)' -MF '$(2).d' \
-o $$@ -c $$<
_M_BUILD_DEP_$(2) = $(value DEPS_BUILD_)
$(2): $(1) $$(_M_BUILD_DEP_$(2))
$$(MAKE_DIRECTORY)
@echo "CC $(1) --> $(2)"
$$(Q)$$($(2)_CC_CMD)
-include $(2).d
endef
# (1) - Source filename
# (2) - Object filename
define EVAL_CXX_RULE
OBJS := $$(OBJS) $(2)
LAST_TARGET_ := $$(LAST_TARGET_) $(2)
$(2)_CXX_CMD = \
$(CXX) \
$$($(ARCH)CXXF) $(CXXF) $(DEPS_CXXF_) $(LDEP_CXXF_) \
$(LDEP_CIF_) $(DEPS_CIF_) $(LDEP_CXXIF_) $(DEPS_CXXIF_) \
-MMD -MP -MT '$(2)' -MF '$(2).d' \
-o $$@ -c $$<
_M_BUILD_DEP_$(2) = $(value DEPS_BUILD_)
$(2): $(1) $$(_M_BUILD_DEP_$(2))
$$(MAKE_DIRECTORY)
@echo "CXX $(1) --> $(2)"
$$(Q)$$($(2)_CXX_CMD)
-include $(2).d
endef
# (1) - Source filename
# (2) - Object filename
define EVAL_ASM_RULE
OBJS := $$(OBJS) $(2)
LAST_TARGET_ := $$(LAST_TARGET_) $(2)
$(2)_ASM_CMD = \
$(CC) \
$$($(ARCH)ASF) $(ASF) $(DEPS_ASF_) $(LDEP_ASF_) \
$(LDEP_ASIF_) $(DEPS_ASIF_) \
-o $$@ -c $$<
_M_BUILD_DEP_$(2) = $(value DEPS_BUILD_)
$(2): $(1) $$(_M_BUILD_DEP_$(2))
$$(MAKE_DIRECTORY)
@echo "AS $(1) --> $(2)"
$$(Q)$$($(2)_ASM_CMD)
endef
# (1) - Library base name
# (2) - Archive filename
define EVAL_AR_RULE
LDEP_LINK_ := $$(value LDEP_LINK_) $(2)
LIBS_BASENAME := $$(LIBS_BASENAME) $(1)
LAST_TARGET_ := $(2)
_M_BUILD_DEP_$(2) = $(value DEPS_BUILD_)
$(2): $(OBJS) $$(_M_BUILD_DEP_$(2))
$$(MAKE_DIRECTORY)
@echo "AR $(OBJS) --> $$@"
$$(Q)$(AR) -r $$@ $(OBJS)
endef
# $(1) - Export symbol name
define EVAL_EXPORT_SHALLOW_DEPS
EXPORTED_DEP_NAMES_ := $$(EXPORTED_DEP_NAMES_) $(ARCH)_$(1)
$(ARCH)DEPS_BUILD_$(1) := $$(value DEPS_BUILD_)
$(ARCH)DEPS_LINK_$(1) := $$(value LDEP_LINK_)
$(ARCH)DEPS_ASF_$(1) := $$(value LDEP_ASF_)
$(ARCH)DEPS_CF_$(1) := $$(value LDEP_CF_)
$(ARCH)DEPS_CXXF_$(1) := $$(value LDEP_CXXF_)
$(ARCH)DEPS_ASIF_$(1) := $$(value LDEP_ASIF_)
$(ARCH)DEPS_CIF_$(1) := $$(value LDEP_CIF_)
$(ARCH)DEPS_CXXIF_$(1) := $$(value LDEP_CXXIF_)
ifneq ($(LIBS_BASENAME),)
$(ARCH)DEPS_LF_$(1) := $$(value LDEP_LF_) -L$(LIB_DIR)
$(ARCH)DEPS_LL_$(1) := $$(value LDEP_LL_) $(patsubst %,-l%,$(LIBS_BASENAME))
else
$(ARCH)DEPS_LF_$(1) := $$(value LDEP_LF_)
$(ARCH)DEPS_LL_$(1) := $$(value LDEP_LL_)
endif
endef
# $(1) - Import symbol name
define EVAL_IMPORT_DEP
IMPORTED_DEP_NAMES_ := $$(IMPORTED_DEP_NAMES_) $(ARCH)_$(1)
DEPS_BUILD_ := $$(value DEPS_BUILD_) $$$$($(ARCH)DEPS_BUILD_$(1))
DEPS_LINK_ := $$(value DEPS_LINK_) $$$$($(ARCH)DEPS_LINK_$(1))
DEPS_ASF_ := $$(value DEPS_ASF_) $$$$($(ARCH)DEPS_ASF_$(1))
DEPS_CF_ := $$(value DEPS_CF_) $$$$($(ARCH)DEPS_CF_$(1))
DEPS_CXXF_ := $$(value DEPS_CXXF_) $$$$($(ARCH)DEPS_CXXF_$(1))
DEPS_ASIF_ := $$(value DEPS_ASIF_) $$$$($(ARCH)DEPS_ASIF_$(1))
DEPS_CIF_ := $$(value DEPS_CIF_) $$$$($(ARCH)DEPS_CIF_$(1))
DEPS_CXXIF_ := $$(value DEPS_CXXIF_) $$$$($(ARCH)DEPS_CXXIF_$(1))
DEPS_LF_ := $$(value DEPS_LF_) $$$$($(ARCH)DEPS_LF_$(1))
DEPS_LL_ := $$(value DEPS_LL_) $$$$($(ARCH)DEPS_LL_$(1))
endef
# (1) - Import symbol names
define EVAL_IMPORT_DEPS
$$(foreach dep,$(1),$$(eval $$(call EVAL_IMPORT_DEP,$$(dep))))
endef
# (1) - Architecture prefix
define EVAL_BEGIN_APPEND_ARCH_FLAGS
ARCH := $(1)
ASF :=
CF :=
CXXF :=
LF :=
LL :=
endef
define EVAL_END_APPEND_ARCH_FLAGS
$(ARCH)ASF := $$($(ARCH)ASF) $$(ASF)
$(ARCH)CF := $$($(ARCH)CF) $$(CF)
$(ARCH)CXXF := $$($(ARCH)CXXF) $$(CXXF)
$(ARCH)LF := $$($(ARCH)LF) $$(LF)
$(ARCH)LL := $$($(ARCH)LL) $$(LL)
ARCH :=
ASF :=
CF :=
CXXF :=
LF :=
LL :=
endef
# $(1) - Include path
define EVAL_ADD_AS_INCLUDE
LDEP_ASIF_ := $$(value LDEP_ASIF_) $$(patsubst %,-I%,$(1))
endef
# $(1) - Include path
define EVAL_ADD_C_INCLUDE
LDEP_CIF_ := $$(value LDEP_CIF_) $$(patsubst %,-I%,$(1))
endef
# $(1) - Include path
define EVAL_ADD_CXX_INCLUDE
LDEP_CXXIF_ := $$(value LDEP_CXXIF_) $$(patsubst %,-I%,$(1))
endef
# $(1) - Flags
define EVAL_ADD_ASF_FLAG
LDEP_ASF_ := $$(value LDEP_ASF_) $(1)
endef
# $(1) - Flags
define EVAL_ADD_CF_FLAG
LDEP_CF_ := $$(value LDEP_CF_) $(1)
endef
# $(1) - Flags
define EVAL_ADD_CXXF_FLAG
LDEP_CXXF_ := $$(value LDEP_CXXF_) $(1)
endef
# $(1) - Flags
define EVAL_ADD_LF_FLAG
LDEP_LF_ := $$(value LDEP_LF_) $(1)
endef
# $(1) - Flags
define EVAL_ADD_LL_FLAG
LDEP_LL_ := $$(value LDEP_LL_) $(1)
endef
# $(1) - Custom build step dependencies
define EVAL_ADD_CUSTOM_BUILD_DEP
DEPS_BUILD_ := $$(value DEPS_BUILD_) $(1)
endef
# $(1) - Custom link step dependencies
define EVAL_ADD_CUSTOM_LINK_DEP
LDEP_LINK_ := $$(value LDEP_LINK_) $(1)
endef
# $(1) - Architecture name
define EVAL_ASSERT_ARCH
ifeq ($$(filter $(1), $$(ALL_ARCH_LIST_)),)
$$(error Architecture $(1) has not been defined)
endif
endef
# -------------------------------------------------------------- INTERNAL RULES
# $(1) - Dependency name to check for
define EVAL_CHECK_IS_EXPORTED
ifeq ($$(filter $(1),$$(EXPORTED_DEP_NAMES_)),)
$$(error Dependency $(1) was imported, but never exported)
endif
endef
define EVAL_COMPARE_IMPORT_EXPORT_LIST
$$(foreach dep,$$(IMPORTED_DEP_NAMES_),$$(eval $$(call EVAL_CHECK_IS_EXPORTED,$$(dep))))
endef
# This checks that all IMPORT_DEPS were eventually matched with an
# EXPORT_SHALLOW_DEPS
.PHONY: METAMAKE_CHECK_EXPORT_LIST
METAMAKE_CHECK_EXPORT_LIST: $$(eval $$(EVAL_COMPARE_IMPORT_EXPORT_LIST)) ;
# ALL_TARGETS wrapper
.PHONY: METAMAKE_ALL
METAMAKE_ALL: $$(ALL_TARGETS) ;
# CLEAN_TARGETS wrapper
.PHONY: METAMAKE_CLEAN
METAMAKE_CLEAN: $$(CLEAN_TARGETS) ;