1#
2# Copyright 2022 Google LLC
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at:
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15#
16
17V ?= @
18
19BUILD_DIR := build
20BIN_DIR := bin
21
22
23#
24# Set `gcc` as default compiler
25#
26
27CC := $(if $(CC)=cc,gcc,$(CC))
28AS := $(if $(AS)=as,$(CC),$(AS))
29LD := $(if $(LD)=ld,$(CC),$(LD))
30
31CFLAGS := $(if $(DEBUG),-O0 -g,-O3)
32CFLAGS += -std=c11 -Wall -Wextra -Wdouble-promotion
33
34
35#
36# Declarations
37#
38
39lib_list :=
40bin_list :=
41
42define add-lib
43    $(eval $(1)_bin ?= $(1).a)
44    $(eval $(1)_bin := $(addprefix $(BIN_DIR)/,$($(1)_bin)))
45
46    lib_list += $(1)
47    LIB += $($(1)_bin)
48endef
49
50define add-bin
51    $(eval $(1)_bin ?= $(1))
52    $(eval $(1)_bin := $(addprefix $(BIN_DIR)/,$($(1)_bin)))
53
54    $($(1)_bin): LDLIBS += $(if $(filter $(LIBC),bionic),\
55      $(filter-out rt pthread,$($(1)_ldlibs)),$($(1)_ldlibs))
56    $($(1)_bin): LDFLAGS += $($(1)_ldflags)
57
58    bin_list += $(1)
59    BIN += $($(1)_bin)
60endef
61
62define set-target
63    $(eval $(1)_obj ?= $(patsubst %.c,%.o,$(filter %.c,$($(1)_src))) \
64                       $(patsubst %.s,%.o,$(filter %.s,$($(1)_src))))
65    $(eval $(1)_obj := $(addprefix $(BUILD_DIR)/,$($(1)_obj)))
66    $(eval $(1)_lib := $(foreach lib, $($(1)_lib), $($(lib)_bin)))
67
68    $($(1)_obj): INCLUDE += $($(1)_include)
69    $($(1)_obj): DEFINE  += $($(1)_define)
70    $($(1)_obj): CFLAGS  += $($(1)_cflags)
71
72    -include $($(1)_obj:.o=.d)
73
74    $($(1)_bin): $($(1)_lib)
75    $($(1)_bin): $($(1)_obj)
76    $($(1)_bin): $($(1)_dependencies)
77
78    .PHONY: $(1)
79    $(1): $($(1)_bin)
80endef
81
82.PHONY: default
83default:
84
85
86INCLUDE += include
87
88SRC_DIR = src
89include $(SRC_DIR)/makefile.mk
90
91TOOLS_DIR = tools
92-include $(TOOLS_DIR)/makefile.mk
93
94TEST_DIR := test
95-include $(TEST_DIR)/makefile.mk
96
97
98#
99# Rules
100#
101
102MAKEFILE_DEPS := $(MAKEFILE_LIST)
103
104$(foreach lib, $(lib_list), $(eval $(call set-target,$(lib))))
105$(foreach bin, $(bin_list), $(eval $(call set-target,$(bin))))
106
107$(BUILD_DIR)/%.o: %.c $(MAKEFILE_DEPS)
108	@echo "  CC      $(notdir $<)"
109	$(V)mkdir -p $(dir $@)
110	$(V)$(CC) $< -c $(CFLAGS) \
111	    $(addprefix -I,$(INCLUDE)) \
112	    $(addprefix -D,$(DEFINE)) -MMD -MF $(@:.o=.d) -o $@
113
114$(BUILD_DIR)/%.o: %.s $(MAKEFILE_DEPS)
115	@echo "  AS      $(notdir $<)"
116	$(V)mkdir -p $(dir $@)
117	$(V)$(AS) $< -c $(CFLAGS) \
118	    $(addprefix -I,$(INCLUDE)) \
119	    $(addprefix -D,$(DEFINE)) -MMD -MF $(@:.o=.d) -o $@
120
121$(LIB): $(MAKEFILE_DEPS)
122	@echo "  AR      $(notdir $@)"
123	$(V)mkdir -p $(dir $@)
124	$(V)$(AR) rcs $@ $(filter %.o,$^)
125
126$(BIN): $(MAKEFILE_DEPS)
127	@echo "  LD      $(notdir $@)"
128	$(V)mkdir -p $(dir $@)
129	$(V)$(LD) $(filter %.o,$^) $(filter %.a,$^) $(LDFLAGS) \
130	    $(addprefix -l,$(LDLIBS)) -o $@
131
132clean:
133	$(V)rm -rf $(BUILD_DIR)
134	$(V)rm -rf $(BIN_DIR)
135
136clean-all: clean
137