summaryrefslogtreecommitdiff
path: root/mk/cores.mk
blob: 55235ee1b0f38f7ea61de02d4ddc7da16fa39ff2 (plain)
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
here = $(if $(mod_path),$(mod_path)/)
mod_path :=
subdir_stack :=

unknown_core = $(error $(if $(2),in core '$(2)': ,)unknown core '$(1)')

all_cores :=
all_stamps :=

top_stamp = $(call core_stamp,$(rule_top))
core_stamp = $(obj)/deps/$(core_info/$(1)/path)/stamp

core_paths_no_dyn = \
  $(patsubst /%,%, \
    $(patsubst /,., \
      $(abspath \
        $(let prefix,$(core_info/$(1)/workdir), \
          $(foreach path_elem,$(core_info/$(1)/$(2)), \
            $(if $(patsubst /%,,$(path_elem)), \
              $(addprefix /$(if $(prefix),$(prefix)/),$(path_elem)), \
              $(path_elem)))))))

core_paths = \
  $(call core_paths_no_dyn,$(1),$(2)) $(call core_paths_no_dyn,$(1),$(call target_var,$(2)))

require_core_paths = \
  $(strip \
    $(let val,$(strip $(call core_paths,$(1),$(2))), \
      $(if $(val),$(val),$(error core '$(1)' must define '$(2)'))))

core_paths_dyn = $(call core_paths,$(1),$(call target_var,$(2)))

define add_core_dyn
  core_info/$(1)/$(call target_var,$(2)) := $(core_info/$(1)/$(call target_var,$(2))) $(3)
endef

require_core_var = \
  $(strip \
    $(let val,$(core_info/$(1)/$(2)), \
      $(if $(val),$(val),$(error core '$(1)' must define '$(2)'))))

core_shell = $(call shell_checked,cd $(here); $(1))

define add_core
  this := core_info/$(1)

  ifneq (,$$($$(this)/path))
    $$(error multiple definitions of core '$(1)': '$$($$(this)/path)' and '$(2)')
  else ifneq (,$$(core_path/$(2)))
    $$(error multiple cores under path '$(2)')
  endif

  $$(this)/path := $(2)
  $$(this)/mod_file := $$(mod_file)
  $$(this)/workdir := $$(mod_path)

  $$(eval $$(call $(3)))

  this :=
  all_cores += $(1)
  core_path/$(2) := $(1)
endef

define add_core_subdir
  core :=
  cores :=
  subdirs :=

  subdir_stack += $$(mod_path)
  mod_path := $$(here)$(1)
  mod_file := $$(here)mod.mk

  include $$(mod_file)

  $$(if $$(core), \
    $$(eval $$(call add_core,$(notdir $(1)),$$(mod_path),core)))

  $$(foreach core,$$(cores), \
    $$(eval $$(call add_core,$$(core),$$(here)$$(core),core/$$(core))))

  $$(foreach subdir,$$(subdirs), \
    $$(eval $$(call add_core_subdir,$$(subdir))))

  mod_path := $$(lastword $$(subdir_stack))
  subdir_stack := $$(filter-out $$(mod_path),$$(subdir_stack))
endef

define setup_dep_tree
  $$(foreach core,$$(all_cores), \
    $$(eval $$(call defer,dep_tree/$$(core),$$$$(call get_core_deps,$$(core)))))
endef

define setup_stamp_rules
  $$(foreach core,$$(all_cores), \
    $$(let stamp,$$(call core_stamp,$$(core)), \
      $$(stamp) \
      $$(eval $$(call add_core_stamp,$$(core),$$(stamp))))): $$(build_makefiles) | $$(obj)
endef

define add_core_stamp
  $(2): $$(core_info/$(1)/mod_file) \
        $$(foreach dep,$$(core_info/$(1)/deps),$$(call core_stamp,$$(dep)))

  all_stamps += $(2)
endef

define get_core_deps
  dep_tree/$(1) :=

  $$(foreach dep,$$(core_info/$(1)/deps), \
    $$(if $$(core_info/$$(dep)/path),,$$(call unknown_core,$$(dep),$(1))) \
    $$(eval dep_tree/$(1) := \
      $$(dep_tree/$$(dep)) $$(filter-out $$(dep_tree/$$(dep)),$$(dep_tree/$(1)))))

  dep_tree/$(1) := $$(strip $$(dep_tree/$(1)))
  dep_tree/$(1) += $(1)
endef

map_core_deps = \
  $(if $(findstring undefined,$(origin $(1)_deps/$(2))), \
    $(eval $(call merge_mapped_deps,$(1),$(2)))) \
  $($(1)_deps/$(2))

define merge_mapped_deps
  $(1)_deps/$(2) := $$(core_info/$(2)/$(1))

  $$(foreach dep,$$(core_info/$(2)/deps), \
    $$(eval $(1)_deps/$(2) := \
      $$(let mapped_dep,$$(call map_core_deps,$(1),$$(dep)), \
        $$(mapped_dep) $$(filter-out $$(mapped_dep),$$($(1)_deps/$(2))))))
endef

define finish_stamp_rules
  $$(all_stamps):
	@mkdir -p $$$$(dirname $$@) && touch $$@
endef