1- pmu-events-y += pmu-events.o
2- JSON = $(shell find pmu-events/arch -name '*.json' -o -name '*.csv')
3- JSON_DIRS = $(shell find pmu-events/arch -type d)
4- JDIR_TEST = pmu-events/arch/test
5- JSON_TEST = $(shell [ -d $(JDIR_TEST) ] && \
6- find $(JDIR_TEST) -name '*.json')
7- JEVENTS_PY = pmu-events/jevents.py
8- METRIC_PY = pmu-events/metric.py
9- METRIC_TEST_PY = pmu-events/metric_test.py
101EMPTY_PMU_EVENTS_C = pmu-events/empty-pmu-events.c
2+ # pmu-events.c will be generated by jevents.py or copied from EMPTY_PMU_EVENTS_C
113PMU_EVENTS_C = $(OUTPUT)pmu-events/pmu-events.c
12- METRIC_TEST_LOG = $(OUTPUT)pmu-events/metric_test.log
13- TEST_EMPTY_PMU_EVENTS_C = $(OUTPUT)pmu-events/test-empty-pmu-events.c
14- EMPTY_PMU_EVENTS_TEST_LOG = $(OUTPUT)pmu-events/empty-pmu-events.log
15- LEGACY_CACHE_PY = pmu-events/make_legacy_cache.py
16- LEGACY_CACHE_JSON = $(OUTPUT)pmu-events/arch/common/common/legacy-cache.json
4+ pmu-events-y += pmu-events.o
175
18- ifeq ($(JEVENTS_ARCH),)
19- JEVENTS_ARCH=$(SRCARCH)
20- endif
21- JEVENTS_MODEL ?= all
6+ # pmu-events.c file is generated in the OUTPUT directory so it needs a
7+ # separate rule to depend on it properly
8+ $(OUTPUT)pmu-events/pmu-events.o: $(PMU_EVENTS_C)
9+ $(call rule_mkdir)
10+ $(call if_changed_dep,cc_o_c)
2211
23- #
24- # Locate/process JSON files in pmu-events/arch/
25- # directory and create tables in pmu-events.c.
26- #
12+ # Message for $(call echo-cmd,cp), possibly remove the src file from
13+ # the destination to save space in the build log.
14+ quiet_cmd_cp = COPY $(patsubst %$<,%,$@) <- $<
2715
16+ # --- NO_JEVENTS=1 build ---
2817ifeq ($(NO_JEVENTS),1)
2918$(PMU_EVENTS_C): $(EMPTY_PMU_EVENTS_C)
3019 $(call rule_mkdir)
31- $(Q)$(call echo-cmd,gen )cp $< $@
20+ $(Q)$(call echo-cmd,cp )cp $< $@
3221else
33- # Functions to extract the model from a extra-metrics.json or extra-metricgroups.json path.
34- model_name = $(shell echo $(1)|sed -e 's@.\+/\(.*\)/extra-metric.*\.json@\1@')
35- vendor_name = $(shell echo $(1)|sed -e 's@.\+/\(.*\)/[^/]*/extra-metric.*\.json@\1@')
22+ # --- Regular build ---
3623
37- # Copy checked-in json to OUTPUT for generation if it's an out of source build
38- ifneq ($(OUTPUT),)
39- # Remove all output directories when any source directory timestamp changes
40- # so there are no stale deleted files
41- JSON_DIRS_ROOT = $(OUTPUT)pmu-events/arch/
42- $(JSON_DIRS_ROOT): $(JSON_DIRS)
43- $(Q)$(call echo-cmd,gen)rm -rf $@
44- $(Q)mkdir -p $@
24+ # Setup the JEVENTS_ARCH and JEVENTS_MODEL
25+ ifeq ($(JEVENTS_ARCH),)
26+ JEVENTS_ARCH=$(SRCARCH)
27+ endif
28+ JEVENTS_MODEL ?= all
4529
46- $(OUTPUT)pmu-events/arch/%: pmu-events/arch/% $(JSON_DIRS_ROOT)
47- $(call rule_mkdir)
48- $(Q)$(call echo-cmd,gen)cp $< $@
30+ # The input json/csv files
31+ SRC_DIR := pmu-events/arch
32+ ifeq ($(JEVENTS_ARCH),all)
33+ SRC_JSON := $(shell find $(SRC_DIR) -name '*.json' -o -name '*.csv')
34+ else
35+ SRC_JSON := $(shell find $(SRC_DIR)/common $(SRC_DIR)/test $(SRC_DIR)/$(JEVENTS_ARCH) -name '*.json' -o -name '*.csv')
4936endif
5037
51- $(LEGACY_CACHE_JSON): $(LEGACY_CACHE_PY) $(JSON_DIRS_ROOT)
38+ # Python to build the generic legacy cache events
39+ LEGACY_CACHE_PY = pmu-events/make_legacy_cache.py
40+ LEGACY_CACHE_JSON = $(OUTPUT)pmu-events/arch/common/common/legacy-cache.json
41+ GEN_JSON = $(LEGACY_CACHE_JSON)
42+
43+ $(LEGACY_CACHE_JSON): $(LEGACY_CACHE_PY)
5244 $(call rule_mkdir)
5345 $(Q)$(call echo-cmd,gen)$(PYTHON) $(LEGACY_CACHE_PY) > $@
5446
47+ # Python to generate architectural metrics
5548GEN_METRIC_DEPS := pmu-events/metric.py pmu-events/common_metrics.py
49+ # Functions to extract the model from an extra-metrics.json or extra-metricgroups.json path.
50+ model_name = $(shell echo $(1)|sed -e 's@.\+/\(.*\)/extra-metric.*\.json@\1@')
51+ vendor_name = $(shell echo $(1)|sed -e 's@.\+/\(.*\)/[^/]*/extra-metric.*\.json@\1@')
5652
53+ ifeq ($(JEVENTS_ARCH),$(filter $(JEVENTS_ARCH),x86 all))
5754# Generate AMD Json
5855ZENS = $(shell ls -d pmu-events/arch/x86/amdzen*)
5956ZEN_METRICS = $(foreach x,$(ZENS),$(OUTPUT)$(x)/extra-metrics.json)
6057ZEN_METRICGROUPS = $(foreach x,$(ZENS),$(OUTPUT)$(x)/extra-metricgroups.json)
58+ GEN_JSON += $(ZEN_METRICS) $(ZEN_METRICGROUPS)
6159
6260$(ZEN_METRICS): pmu-events/amd_metrics.py $(GEN_METRIC_DEPS)
6361 $(call rule_mkdir)
@@ -67,10 +65,14 @@ $(ZEN_METRICGROUPS): pmu-events/amd_metrics.py $(GEN_METRIC_DEPS)
6765 $(call rule_mkdir)
6866 $(Q)$(call echo-cmd,gen)$(PYTHON) $< -metricgroups $(call model_name,$@) pmu-events/arch > $@
6967
68+ endif
69+
70+ ifeq ($(JEVENTS_ARCH),$(filter $(JEVENTS_ARCH),arm64 all))
7071# Generate ARM Json
7172ARMS = $(shell ls -d pmu-events/arch/arm64/arm/*|grep -v cmn)
7273ARM_METRICS = $(foreach x,$(ARMS),$(OUTPUT)$(x)/extra-metrics.json)
7374ARM_METRICGROUPS = $(foreach x,$(ARMS),$(OUTPUT)$(x)/extra-metricgroups.json)
75+ GEN_JSON += $(ARM_METRICS) $(ARM_METRICGROUPS)
7476
7577$(ARM_METRICS): pmu-events/arm64_metrics.py $(GEN_METRIC_DEPS)
7678 $(call rule_mkdir)
@@ -80,10 +82,14 @@ $(ARM_METRICGROUPS): pmu-events/arm64_metrics.py $(GEN_METRIC_DEPS)
8082 $(call rule_mkdir)
8183 $(Q)$(call echo-cmd,gen)$(PYTHON) $< -metricgroups $(call vendor_name,$@) $(call model_name,$@) pmu-events/arch > $@
8284
85+ endif
86+
87+ ifeq ($(JEVENTS_ARCH),$(filter $(JEVENTS_ARCH),x86 all))
8388# Generate Intel Json
8489INTELS = $(shell ls -d pmu-events/arch/x86/*|grep -v amdzen|grep -v mapfile.csv)
8590INTEL_METRICS = $(foreach x,$(INTELS),$(OUTPUT)$(x)/extra-metrics.json)
8691INTEL_METRICGROUPS = $(foreach x,$(INTELS),$(OUTPUT)$(x)/extra-metricgroups.json)
92+ GEN_JSON += $(INTEL_METRICS) $(INTEL_METRICGROUPS)
8793
8894$(INTEL_METRICS): pmu-events/intel_metrics.py $(GEN_METRIC_DEPS)
8995 $(call rule_mkdir)
@@ -93,55 +99,130 @@ $(INTEL_METRICGROUPS): pmu-events/intel_metrics.py $(GEN_METRIC_DEPS)
9399 $(call rule_mkdir)
94100 $(Q)$(call echo-cmd,gen)$(PYTHON) $< -metricgroups $(call model_name,$@) pmu-events/arch > $@
95101
96- GEN_JSON = $(patsubst %,$(OUTPUT)%,$(JSON)) \
97- $(LEGACY_CACHE_JSON) \
98- $(JSON_DIRS) \
99- $(ZEN_METRICS) $(ZEN_METRICGROUPS) \
100- $(ARM_METRICS) $(ARM_METRICGROUPS) \
101- $(INTEL_METRICS) $(INTEL_METRICGROUPS)
102+ endif
103+
104+ OUT_DIR := $(OUTPUT)pmu-events/arch
105+
106+ ifeq ($(OUTPUT),)
107+ OUT_JSON := $(SRC_JSON)
108+ ORPHAN_FILES :=
109+ else
110+ # Things that need to be built in the OUTPUT directory. Note, ensure
111+ # there is a slash after the directory name so that it matches what
112+ # $(dir) gives in COPY_RULE.
113+ OUT_JSON := $(patsubst $(SRC_DIR)/%,$(OUT_DIR)/%,$(SRC_JSON))
114+ OUT_DIRS := $(sort $(patsubst %/,%,$(dir $(OUT_JSON))))
115+
116+ # Things already in the OUTPUT directory
117+ CUR_OUT_JSON := $(shell [ -d $(OUT_DIR) ] && find $(OUT_DIR) -type f)
118+
119+ # Things in the OUTPUT directory but shouldn't be there as computed by
120+ # OUT_JSON and GEN_JSON.
121+ ORPHAN_FILES := $(filter-out $(OUT_JSON) $(GEN_JSON),$(CUR_OUT_JSON))
122+
123+ # Message for $(call echo-cmd,mkd). There is already a mkdir message
124+ # but it assumes $@ is a file to mkdir the directory for.
125+ quiet_cmd_mkd = MKDIR $@
126+
127+ $(OUT_DIRS):
128+ $(Q)$(call echo-cmd,mkd)mkdir -p $@
129+
130+ # Explicitly generate rules to copy SRC_JSON files as $(dir) cannot
131+ # apply to $@ in a dependency. Exclude from the copy rules any that
132+ # look like they are copying generated json. This happens as a perf
133+ # build within the tools/perf directory will leave generated json
134+ # files within the tree, these then get picked up by SRC_JSON find.
135+ define COPY_RULE
136+ $(2): $(1) | $(3)
137+ $$(Q)$$(call echo-cmd,cp)cp $(1) $(2)
138+ endef
139+ $(foreach src,$(SRC_JSON), \
140+ $(eval dest := $(patsubst $(SRC_DIR)/%,$(OUT_DIR)/%,$(src))) \
141+ $(eval ddir := $(patsubst %/,%,$(dir $(dest)))) \
142+ $(if $(filter $(dest),$(GEN_JSON)),, \
143+ $(eval $(call COPY_RULE,$(src),$(dest),$(ddir))) \
144+ ) \
145+ )
146+
147+ endif # ifneq ($(OUTPUT),)
148+
149+ JEVENTS_PY = pmu-events/jevents.py
150+ METRIC_PY = pmu-events/metric.py
151+
152+ # Rule to run the metric test.
153+ METRIC_TEST_PY = pmu-events/metric_test.py
154+ METRIC_TEST_LOG = $(OUTPUT)pmu-events/metric_test.log
102155
103156$(METRIC_TEST_LOG): $(METRIC_TEST_PY) $(METRIC_PY)
104157 $(call rule_mkdir)
105158 $(Q)$(call echo-cmd,test)$(PYTHON) $< 2> $@ || (cat $@ && false)
106159
107- $(TEST_EMPTY_PMU_EVENTS_C): $(GEN_JSON) $(JSON_TEST) $(JEVENTS_PY) $(METRIC_PY) $(METRIC_TEST_LOG)
160+ # Rule to create then ensure the empty-pmu-events.c is in sync.
161+ TEST_EMPTY_PMU_EVENTS_C = $(OUTPUT)pmu-events/test-empty-pmu-events.c
162+ EMPTY_PMU_EVENTS_TEST_LOG = $(OUTPUT)pmu-events/empty-pmu-events.log
163+
164+ $(TEST_EMPTY_PMU_EVENTS_C): $(OUT_JSON) $(GEN_JSON) $(JEVENTS_PY) $(METRIC_PY)
108165 $(call rule_mkdir)
109166 $(Q)$(call echo-cmd,gen)$(PYTHON) $(JEVENTS_PY) none none $(OUTPUT)pmu-events/arch $@
110167
111168$(EMPTY_PMU_EVENTS_TEST_LOG): $(EMPTY_PMU_EVENTS_C) $(TEST_EMPTY_PMU_EVENTS_C)
112169 $(call rule_mkdir)
113170 $(Q)$(call echo-cmd,test)diff -u $^ 2> $@ || (cat $@ && false)
114171
172+
173+ # Dependencies for jevents.py
174+ JEVENTS_DEPS := $(OUT_JSON) $(GEN_JSON) $(JEVENTS_PY) $(METRIC_PY) $(EMPTY_PMU_EVENTS_TEST_LOG) $(METRIC_TEST_LOG)
175+
176+ # Rules to run mypy if enabled.
115177ifdef MYPY
116- PMU_EVENTS_PY_TESTS := $(wildcard *.py)
117- PMU_EVENTS_MYPY_TEST_LOGS := $(JEVENTS_PY_TESTS:%=%.mypy_log)
118- else
119- PMU_EVENTS_MYPY_TEST_LOGS :=
178+ define MYPY_RULE
179+ $(2): $(1)
180+ $$(Q)$$(call echo-cmd,test)mypy $(1) > $(2) || (cat $(2) && rm $(2) && false)
181+ endef
182+ $(foreach src,$(wildcard pmu-events/*.py), \
183+ $(eval dest := $(patsubst pmu-events/%,$(OUTPUT)pmu-events/%.mypy_log,$(src))) \
184+ $(eval $(call MYPY_RULE,$(src),$(dest))) \
185+ )
186+
187+ MYPY_INPUTS := $(wildcard pmu-events/*.py)
188+ MYPY_OUTPUTS := $(patsubst pmu-events/%,$(OUTPUT)pmu-events/%.mypy_log,$(MYPY_INPUTS))
189+ JEVENTS_DEPS += $(MYPY_OUTPUTS)
120190endif
121191
122- $(OUTPUT)%.mypy_log: %
123- $(call rule_mkdir)
124- $(Q)$(call echo-cmd,test)mypy "$<" > $@ || (cat $@ && rm $@ && false)
125-
192+ # Rules to run pylint if enabled.
126193ifdef PYLINT
127- PMU_EVENTS_PY_TESTS := $(wildcard *.py)
128- PMU_EVENTS_PYLINT_TEST_LOGS := $(JEVENTS_PY_TESTS:%=%.pylint_log)
129- else
130- PMU_EVENTS_PYLINT_TEST_LOGS :=
194+ define PYLINT_RULE
195+ $(2): $(1)
196+ $$(Q)$$(call echo-cmd,test)pylint $(1) > $(2) || (cat $(2) && rm $(2) && false)
197+ endef
198+ $(foreach src,$(wildcard pmu-events/*.py), \
199+ $(eval dest := $(patsubst pmu-events/%,$(OUTPUT)pmu-events/%.pylint_log,$(src))) \
200+ $(eval $(call PYLINT_RULE,$(src),$(dest))) \
201+ )
202+
203+ PYLINT_INPUTS := $(wildcard pmu-events/*.py)
204+ PYLINT_OUTPUTS := $(patsubst pmu-events/%,$(OUTPUT)pmu-events/%.pylint_log,$(PYLINT_INPUTS))
205+ JEVENTS_DEPS += $(PYLINT_OUTPUTS)
131206endif
132207
133- $(OUTPUT)%.pylint_log: %
134- $(call rule_mkdir )
135- $(Q)$(call echo-cmd,test)pylint "$<" > $@ || (cat $@ && rm $@ && false)
208+ # If there are orphaned files remove them.
209+ ifneq ($(strip $(ORPHAN_FILES)), )
210+ .PHONY: prune_orphans
136211
137- $(PMU_EVENTS_C): $(GEN_JSON) $(JSON_TEST) $(JEVENTS_PY) $(METRIC_PY) $(METRIC_TEST_LOG) \
138- $(EMPTY_PMU_EVENTS_TEST_LOG) $(PMU_EVENTS_MYPY_TEST_LOGS) $(PMU_EVENTS_PYLINT_TEST_LOGS)
139- $(call rule_mkdir)
140- $(Q)$(call echo-cmd,gen)$(PYTHON) $(JEVENTS_PY) $(JEVENTS_ARCH) $(JEVENTS_MODEL) $(OUTPUT)pmu-events/arch $@
212+ # Message for $(call echo-cmd,rm). Generally cleaning files isn't part
213+ # of a build step.
214+ quiet_cmd_rm = RM $^
215+
216+ prune_orphans: $(ORPHAN_FILES)
217+ $(Q)$(call echo-cmd,rm)rm -f $^
218+
219+ JEVENTS_DEPS += prune_orphans
141220endif
142221
143- # pmu-events.c file is generated in the OUTPUT directory so it needs a
144- # separate rule to depend on it properly
145- $(OUTPUT)pmu-events/pmu-events.o : $(PMU_EVENTS_C )
222+ # Finally, the rule to build pmu-events.c using jevents.py. All test
223+ # and inputs are dependencies.
224+ $(PMU_EVENTS_C) : $(JEVENTS_DEPS )
146225 $(call rule_mkdir)
147- $(call if_changed_dep,cc_o_c)
226+ $(Q)$(call echo-cmd,gen)$(PYTHON) $(JEVENTS_PY) $(JEVENTS_ARCH) $(JEVENTS_MODEL) $(OUT_DIR) $@
227+
228+ endif # ifeq ($(NO_JEVENTS),1)
0 commit comments