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 -Wvla -pedantic
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                       $(patsubst %.cc,%.o,$(filter %.cc,$($(1)_src))))
66    $(eval $(1)_obj := $(addprefix $(BUILD_DIR)/,$($(1)_obj)))
67    $(eval $(1)_lib := $(foreach lib, $($(1)_lib), $($(lib)_bin)))
68
69    $($(1)_obj): INCLUDE  += $($(1)_include)
70    $($(1)_obj): DEFINE   += $($(1)_define)
71    $($(1)_obj): CFLAGS   += $($(1)_cflags)
72    $($(1)_obj): CXXFLAGS += $($(1)_cxxflags)
73
74    -include $($(1)_obj:.o=.d)
75
76    $($(1)_bin): $($(1)_lib)
77    $($(1)_bin): $($(1)_obj)
78    $($(1)_bin): $($(1)_dependencies)
79
80    .PHONY: $(1)
81    $(1): $($(1)_bin)
82endef
83
84.PHONY: default
85default:
86
87
88INCLUDE += include
89
90SRC_DIR = src
91include $(SRC_DIR)/makefile.mk
92
93TOOLS_DIR = tools
94-include $(TOOLS_DIR)/makefile.mk
95
96TEST_DIR := test
97-include $(TEST_DIR)/makefile.mk
98
99FUZZ_DIR := fuzz
100-include $(FUZZ_DIR)/makefile.mk
101
102
103#
104# Rules
105#
106
107MAKEFILE_DEPS := $(MAKEFILE_LIST)
108
109$(foreach lib, $(lib_list), $(eval $(call set-target,$(lib))))
110$(foreach bin, $(bin_list), $(eval $(call set-target,$(bin))))
111
112$(BUILD_DIR)/%.o: %.c $(MAKEFILE_DEPS)
113	@echo "  CC      $(notdir $<)"
114	$(V)mkdir -p $(dir $@)
115	$(V)$(CC) $< -c $(CFLAGS) \
116	    $(addprefix -I,$(INCLUDE)) \
117	    $(addprefix -D,$(DEFINE)) -MMD -MF $(@:.o=.d) -o $@
118
119$(BUILD_DIR)/%.o: %.s $(MAKEFILE_DEPS)
120	@echo "  AS      $(notdir $<)"
121	$(V)mkdir -p $(dir $@)
122	$(V)$(AS) $< -c $(CFLAGS) \
123	    $(addprefix -I,$(INCLUDE)) \
124	    $(addprefix -D,$(DEFINE)) -MMD -MF $(@:.o=.d) -o $@
125
126$(BUILD_DIR)/%.o: %.cc $(MAKEFILE_DEPS)
127	@echo "  CXX     $(notdir $<)"
128	$(V)mkdir -p $(dir $@)
129	$(V)$(CXX) $< -c $(CXXFLAGS) \
130	    $(addprefix -I,$(INCLUDE)) \
131	    $(addprefix -D,$(DEFINE)) -MMD -MF $(@:.o=.d) -o $@
132
133$(LIB): $(MAKEFILE_DEPS)
134	@echo "  AR      $(notdir $@)"
135	$(V)mkdir -p $(dir $@)
136	$(V)$(AR) rcs $@ $(filter %.o,$^)
137
138$(BIN): $(MAKEFILE_DEPS)
139	@echo "  LD      $(notdir $@)"
140	$(V)mkdir -p $(dir $@)
141	$(V)$(LD) $(filter %.o,$^) $(filter %.a,$^) $(LDFLAGS) \
142	    $(addprefix -l,$(LDLIBS)) -o $@
143
144clean:
145	$(V)rm -rf $(BUILD_DIR)
146	$(V)rm -rf $(BIN_DIR)
147
148clean-all: clean
149