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)
32LDFLAGS := $(if $(DEBUG),-O0 -g,-O3)
33
34CFLAGS += -std=c11 -Wall -Wextra -Wdouble-promotion -Wvla -pedantic
35
36TARGET = $(lastword $(shell $(CC) -v 2>&1 | grep "Target: "))
37
38LIB_SHARED := true
39LIB_SUFFIX := so
40
41ifeq ($(TARGET),wasm32)
42  LIB_SHARED := false
43  LIB_SUFFIX := wasm
44  CFLAGS += -Iwasm -mbulk-memory
45  LDFLAGS += -nostdlib -Wl,--no-entry -Wl,--export-dynamic
46endif
47
48ifneq ($(LC3_PLUS),)
49  DEFINE += LC3_PLUS=$(LC3_PLUS)
50endif
51
52ifneq ($(LC3_PLUS_HR),)
53  DEFINE += LC3_PLUS_HR=$(LC3_PLUS_HR)
54endif
55
56
57#
58# Declarations
59#
60
61lib_list :=
62bin_list :=
63
64define add-lib
65    $(eval $(1)_bin ?= $(1).$(LIB_SUFFIX))
66    $(eval $(1)_bin := $(addprefix $(BIN_DIR)/,$($(1)_bin)))
67
68    lib_list += $(1)
69    LIB += $($(1)_bin)
70endef
71
72define add-bin
73    $(eval $(1)_bin ?= $(1))
74    $(eval $(1)_bin := $(addprefix $(BIN_DIR)/,$($(1)_bin)))
75
76    $($(1)_bin): LDLIBS += $(if $(filter $(LIBC),bionic),\
77      $(filter-out rt pthread,$($(1)_ldlibs)),$($(1)_ldlibs))
78    $($(1)_bin): LDFLAGS += $($(1)_ldflags)
79
80    bin_list += $(1)
81    BIN += $($(1)_bin)
82endef
83
84define set-target
85    $(eval $(1)_obj ?= $(patsubst %.c,%.o,$(filter %.c,$($(1)_src))) \
86                       $(patsubst %.s,%.o,$(filter %.s,$($(1)_src))) \
87                       $(patsubst %.cc,%.o,$(filter %.cc,$($(1)_src))))
88    $(eval $(1)_obj := $(addprefix $(BUILD_DIR)/,$($(1)_obj)))
89
90    $($(1)_obj): INCLUDE  += $($(1)_include)
91    $($(1)_obj): DEFINE   += $($(1)_define)
92    $($(1)_obj): CFLAGS   += $($(1)_cflags)
93    $($(1)_obj): CXXFLAGS += $($(1)_cxxflags)
94
95    -include $($(1)_obj:.o=.d)
96
97    $($(1)_bin): $($(1)_obj)
98    $($(1)_bin): $($(1)_dependencies)
99
100    .PHONY: $(1)
101    $(1): $($(1)_bin)
102endef
103
104.PHONY: default
105default:
106
107
108INCLUDE += include
109
110SRC_DIR = src
111include $(SRC_DIR)/makefile.mk
112
113TOOLS_DIR = tools
114-include $(TOOLS_DIR)/makefile.mk
115
116TEST_DIR := test
117-include $(TEST_DIR)/makefile.mk
118
119FUZZ_DIR := fuzz
120-include $(FUZZ_DIR)/makefile.mk
121
122
123#
124# Rules
125#
126
127MAKEFILE_DEPS := $(MAKEFILE_LIST)
128
129$(foreach lib, $(lib_list), $(eval $(call set-target,$(lib))))
130$(foreach bin, $(bin_list), $(eval $(call set-target,$(bin))))
131
132$(BUILD_DIR)/%.o: %.c $(MAKEFILE_DEPS)
133	@echo "  CC      $(notdir $<)"
134	$(V)mkdir -p $(dir $@)
135	$(V)$(CC) $< -c $(CFLAGS) \
136	    $(addprefix -I,$(INCLUDE)) \
137	    $(addprefix -D,$(DEFINE)) -MMD -MF $(@:.o=.d) -o $@
138
139$(BUILD_DIR)/%.o: %.s $(MAKEFILE_DEPS)
140	@echo "  AS      $(notdir $<)"
141	$(V)mkdir -p $(dir $@)
142	$(V)$(AS) $< -c $(CFLAGS) \
143	    $(addprefix -I,$(INCLUDE)) \
144	    $(addprefix -D,$(DEFINE)) -MMD -MF $(@:.o=.d) -o $@
145
146$(BUILD_DIR)/%.o: %.cc $(MAKEFILE_DEPS)
147	@echo "  CXX     $(notdir $<)"
148	$(V)mkdir -p $(dir $@)
149	$(V)$(CXX) $< -c $(CXXFLAGS) \
150	    $(addprefix -I,$(INCLUDE)) \
151	    $(addprefix -D,$(DEFINE)) -MMD -MF $(@:.o=.d) -o $@
152
153ifeq ($(LIB_SHARED),true)
154    $(LIB): CFLAGS += -fvisibility=hidden -flto -fPIC
155    $(LIB): LDFLAGS += -flto -shared
156endif
157
158$(LIB): $(MAKEFILE_DEPS)
159	@echo "  LD      $(notdir $@)"
160	$(V)mkdir -p $(dir $@)
161	$(V)$(LD) $(filter %.o,$^) $(LDFLAGS) -o $@
162
163$(BIN): $(MAKEFILE_DEPS)
164	@echo "  LD      $(notdir $@)"
165	$(V)mkdir -p $(dir $@)
166	$(V)$(LD) $(filter %.o,$^) \
167	    $(LDFLAGS) -L $(BIN_DIR) $(addprefix -l,$(LDLIBS)) -o $@
168
169clean:
170	$(V)rm -rf $(BUILD_DIR)
171	$(V)rm -rf $(BIN_DIR)
172
173clean-all: clean
174