summaryrefslogtreecommitdiff
path: root/Makefile.ide
blob: a87ea0b80977b17e03dca0996fd003c15bf49fd4 (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
137
138
139
140
141
142
143
# -*- makefile -*-
# vim: set filetype=make :
# Copyright 2022 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
#
# Embedded Controller firmware build system - IDE support
#
# One caveat with this approach is that we still don't capture modified make
# variables that are associated with a specific build target, like the following:
#
# $(out)/RW/common/blah.o: CFLAGS += -g
#
# This is because our compile commands json targets will not match this rule.

# If env EXTERNAL_TRUNK_PATH is defined, we use this to build the
# absolute path to the ec directory. Otherwise, we just take the abspath of ".".
ide-ec-path-ext = \
	$(if $(EXTERNAL_TRUNK_PATH),$(EXTERNAL_TRUNK_PATH)/src/platform/ec)
ide-ec-path-abs = $(abspath .)
ide-ec-path = $(or $(ide-ec-path-ext),$(ide-ec-path-abs))

# Clang doesn't support these GCC options.
ide-filters = -mno-sched-prolog -fconserve-stack

# The complete compile_commands.json targets.
ide-compile-cmds-y                        = $(out)/RW/compile_commands.json
ide-compile-cmds-$(CONFIG_FW_INCLUDE_RO) += $(out)/RO/compile_commands.json
ide-compile-cmds-y                       += $(out)/util/compile_commands.json

# All individual <src_file>.compile_cmds.json targets.
ide-rw-objs = $(rw-objs:.o=.compile_cmd.json)
ide-ro-objs = $(ro-objs:.o=.compile_cmd.json)

ide-build-utils    = $(build-utils:=.compile_cmd.json)
ide-host-utils     = $(host-utils:=.compile_cmd.json)
ide-host-utils-cxx = $(host-utils-cxx:=.compile_cmd.json)

ide-utils = $(ide-build-utils) $(ide-host-utils) $(ide-host-utils-cxx)

# The all-ide-compile-cmds target takes about 2 minutes using 8 cores when all
# work is replaced by the |true| command. Thus, the build system itself
# takes 2m independent of the text manipulation.
.PHONY: all-ide-compile-cmds
all-ide-compile-cmds: $(foreach b, $(BOARDS), ide-compile-cmds-$(b))
ide-compile-cmds-%:
	$(MAKE) BOARD=$* V=$(V) ide-compile-cmds

.PHONY: ide-compile-cmds
ide-compile-cmds: $(ide-compile-cmds-y)

# All but the last file/json-object need to have a trailing comma.
#
# The first sed line prepends 4 spaces to all lines and then adds a
# comma + implicit-newline to the end of the last line of the file.
# The second sed line prepends 4 spaces to all lines and then adds an
# implicit new line.
cmd_combine_compile_cmd_json =                                                 \
	printf '[\n'                                                      >$@ ;\
	echo $^ | xargs -n1 | head -n-1 | xargs -n1 sed 's/^/    /;$$s/$$/,/'  \
									 >>$@ ;\
	sed 's/^/    /' $(lastword $^)                                   >>$@ ;\
	printf ']\n'                                                     >>$@ ;

$(out)/RW/compile_commands.json: override BLD := RW
$(out)/RW/compile_commands.json: private objs := $(rw-objs)
$(out)/RW/compile_commands.json: $(ide-rw-objs)
$(out)/RW/compile_commands.json: $(ide-utils)
	$(call quiet,combine_compile_cmd_json,COMBINE)
$(out)/RO/compile_commands.json: override BLD := RO
$(out)/RO/compile_commands.json: private objs := $(ro-objs)
$(out)/RO/compile_commands.json: $(ide-ro-objs)
$(out)/RO/compile_commands.json: $(ide-utils)
	$(call quiet,combine_compile_cmd_json,COMBINE)
$(out)/util/compile_commands.json: $(ide-utils)
	$(call quiet,combine_compile_cmd_json,COMBINE)

# Quote all words and add a comma between words.
# The quotes are applied as \", so that they will escape shell removal.
#
# $(1) - The space separated list of words.
ide-comma = ,
ide-space = $() $()
ide-esc-quoted = $(patsubst %,\"%\",$(1))
cmd_json_list = $(subst $(ide-space),$(ide-comma)$(ide-space),$(ide-esc-quoted))

# Replace any ".compile_cmd.json" with ".o" and filter out $(ide-filters) words.
# The replace is needed because we are invoking build commands from within our
# make rules that have targets set to files of type .compile_cmd.json.
# The compile commands will use special variables that pull this name into
# the command.
#
# $(1) - The compilation command.
# $(2) - The original target extension, like ".o" or "".
cmd_rep_filter = $(subst .compile_cmd.json,$(2),$(filter-out $(ide-filters),$(1)))

# Form a compile command JSON block.
#
# $(1) - Used by quiet function, but it is this command name.
# $(2) - Used by quiet function, but it is the pretty action label.
# $(3) - The compilation command to place in the JSON blob.
# $(4) - The original target extension, like ".o" or "".
# $(5) - The source file this compile command applies to.
cmd_to_compile_cmd_json =                                                      \
	printf '{\n'                                                     >$@  ;\
	printf '    "arguments": [\n'                                   >>$@  ;\
	printf '        %s\n'                                                  \
	  $(call cmd_json_list,$(call cmd_rep_filter,$(3),$(4)))        >>$@  ;\
	printf '    ],\n'                                               >>$@  ;\
	printf '    "directory": "$(ide-ec-path)",\n'                   >>$@  ;\
	printf '    "file": "$(5)"\n'                                   >>$@  ;\
	printf '}\n'                                                    >>$@  ;

# Disable ccache, since this is only going to control whether the ccache
# executable shows in the compile_commands.json file.
%.compile_cmd.json: CCACHE :=

$(out)/RO/%.compile_cmd.json:%.c
	$(call quiet,to_compile_cmd_json,JSON   ,$(cmd_c_to_o),.o,$<)
$(out)/RW/%.compile_cmd.json:%.c
	$(call quiet,to_compile_cmd_json,JSON   ,$(cmd_c_to_o),.o,$<)

$(out)/RO/%.compile_cmd.json:%.cc
	$(call quiet,to_compile_cmd_json,JSON   ,$(cmd_cxx_to_o),.o,$<)
$(out)/RW/%.compile_cmd.json: %.cc
	$(call quiet,to_compile_cmd_json,JSON   ,$(cmd_cxx_to_o),.o,$<)

$(out)/RO/%.compile_cmd.json:%.S
	$(call quiet,to_compile_cmd_json,JSON   ,$(cmd_c_to_o),.o,$<)
$(out)/RW/%.compile_cmd.json:%.S
	$(call quiet,to_compile_cmd_json,JSON   ,$(cmd_c_to_o),.o,$<)

$(ide-build-utils): $(out)/%.compile_cmd.json:$(build-srcs)
	$(call quiet,to_compile_cmd_json,JSON   ,$(cmd_c_to_build),\
		$(EMPTY),$*.c)

$(ide-host-utils): $(out)/%.compile_cmd.json:$(host-srcs)
	$(call quiet,to_compile_cmd_json,JSON   ,$(cmd_c_to_host),\
		$(EMPTY),$*.c)

$(ide-host-utils-cxx): $(out)/%.compile_cmd.json:$(host-srcs-cxx)
	$(call quiet,to_compile_cmd_json,JSON   ,$(cmd_cxx_to_host),\
		$(EMPTY),$*.cc)