summaryrefslogtreecommitdiffstats
path: root/build/TFbuild.main
blob: 36c580b238144d16654f3f69a3ed57f03093b44d (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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
# call once recursively so we get rid of default rules and variables
ifndef RECURSIVE

all:

Makefile: ;

%:
	@$(MAKE) -rR --no-print-directory RECURSIVE=1 $(MAKECMDGOALS)

else

# default target
all: libs progs
	@:

.SECONDEXPANSION:

# default directories
DESTDIR		?=
SBINDIR		?= /usr/sbin
CONFDIR		?= /etc/$(PACKAGE)
MANDIR		?= /usr/share/man
DOCDIR		?= /usr/share/doc/$(PACKAGE)
STATEDIR	?= /var/run

# OS and architecture detection
UNAME_OS	:= $(shell uname -s)
UNAME_ARCH	:= $(shell uname -m)

ifeq ($(UNAME_OS),Linux)
OS_LINUX	:= y
OS_UNIX		:= y
else
$(error Sorry your operating system kernel ($(UNAME_OS)) is not supported yet.)
endif

ifeq ($(patsubst i%86,i86,$(UNAME_ARCH)),i86)
ARCH_X86	:= y
else
$(error Sorry your architecture ($(UNAME_ARCH)) is not supported yet.)
endif

# utilities and default flags for them.
CROSS_COMPILE	?=
CC		:= $(CROSS_COMPILE)gcc
AR		:= $(CROSS_COMPILE)ar
RANLIB		:= $(CROSS_COMPILE)ranlib
LD		:= $(CROSS_COMPILE)ld
INSTALL		:= install
INSTALLDIR	:= $(INSTALL) -d

CFLAGS		:= -Wall -Wstrict-prototypes -D_GNU_SOURCE -std=gnu99
CFLAGS_ALL	?= -g -O2
LDFLAGS		:= $(LDFLAGS)
LDFLAGS_ALL	?= -g

# some helpers
PHONY:=all libs progs allobjdirs arguments-changed
build-enter:=$(TFBUILD)TFbuild.enter
build-leave:=$(TFBUILD)TFbuild.leave
comma:=,
squote:='
empty:=
space:=$(empty) $(empty)
separator:=--

ifdef V
  ifeq ("$(origin V)", "command line")
    VERBOSE = $(V)
  endif
endif
ifndef VERBOSE
  VERBOSE = 0
endif
ifeq ($(VERBOSE),1)
  quiet =
  Q =
else
  quiet=quiet_
  Q = @
endif
ifneq ($(findstring s,$(MAKEFLAGS)),)
  quiet=silent_
endif

# recursion related stuff
srctree			:=
objtree			:= obj/
current-dir		:=
current-dirc		:=
recursion-level		= $(words $(current-dirc))
next-recursion-level	= $(words $(current-dirc) dummy)
objdir			= $(objtree)$(current-dir)
srcdir			= $(srctree)$(current-dir)

# globals
all-progs		:=
all-libs		:=
local-vars		:= CFLAGS LDFLAGS LIBS

# helper macros for targets
escsq = $(subst $(squote),'\$(squote)',$1)
printable-target = $(patsubst $(objtree)%,%,$@)
depfile = $(subst $(comma),_,$(@).d)
#arg-check-prereq = $(if $(arg-check),arguments-changed \
	#$(warning arg-check $(arg-check))\
	#$(warning old $@ - $(cmd_$(@)))\
	#$(warning new $1 - $(cmd_$(1)))\
	#)
arg-check-prereq = $(if $(arg-check),arguments-changed)
arg-check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$(@))) \
                    $(filter-out $(cmd_$(@)), $(cmd_$(1))) )
echo-cmd = $(if $($(quiet)cmd_$(1)),\
	echo '  $(call escsq,$($(quiet)cmd_$(1)))$(echo-why)';)
make-cmd = $(subst \#,\\\#,$(subst $$,$$$$,$(call escsq,$(cmd_$(1)))))
cmd = @$(echo-cmd) $(cmd_$(1))
primary_source = $(firstword $^)

#target-objects2=$(addprefix $(objdir),$(if $(filter-out $(origin $(1)-objs-y),undefined),$($(1)-objs-y),$(1).o))
#target-objects=$(warning target-objects $(1)=$(target-objects2))$(target-objects2)
target-objects=$(addprefix $(objdir),$(if $(filter-out $(origin $(1)-objs-y),undefined),$($(1)-objs-y),$(1).o))

# why - tell all prerequisites that have changed
ifeq ($(VERBOSE),2)
why = - due to $(filter-out $(PHONY),$?) $(filter $(PHONY),$^)
echo-why = $(call escsq, $(strip $(why)))
endif

# rules for targets
define CreateDirectory
ifeq ($(filter createdir-$(1),$(PHONY)),)
PHONY+=createdir-$(1)
ifneq ($(shell [ -d $(1) ] && echo yes), yes)
createdir-$(1):
	$(Q)mkdir -p $(1)
allobjdirs: createdir-$(1)
endif
endif
endef

define CallRule
	@set -e;							\
	$(rule_$(1))
endef

define ExecuteCommand
	@set -e;							\
	$(echo-cmd) $(cmd_$(1));					\
	echo 'cmd_$@ := $(make-cmd)' > $(@).cmd
endef

define MemoizeVariable
ifneq ($($(1)),)
$(current-dir)--$(1):=$($(1))
$(1):=
endif
endef

define PushVariable
inherit-$(1)-$(recursion-level):=$($(1))
endef

define PopVariable
$(current-dir)--$(1):=$($(1))
$(1):=$(inherit-$(1)-$(recursion-level))
endef

define MemoizeAndPopVariable
$(current-dir)--$(1):=$($(1))
$(1):=$(inherit-$(1)-$(recursion-level))
endef

# GCC C-compiler
c_flags		= -Wp,-MD,$(depfile),-MT,$@ $(CFLAGS_ALL) \
	$($(dir $(printable-target))--CFLAGS) \
	$($(dir $(printable-target))--CFLAGS_$(notdir $(primary_source)))

quiet_cmd_cc_o_c = CC      $(printable-target)
      cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $(primary_source)

define rule_cc_o_c
	$(call echo-cmd,cc_o_c) $(cmd_cc_o_c);			\
	(echo 'cmd_$@ := $(call make-cmd,cc_o_c)';		\
	 echo; cat $(depfile) ; echo ;				\
	 sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//'	\
	     -e '/^$$/ d' -e 's/$$/ :/' < $(depfile) )		\
		> $@.cmd ;					\
	rm $(depfile)
endef

$(objtree)%.o: $(srctree)%.c $$(call arg-check-prereq,cc_o_c) |allobjdirs
	$(call CallRule,cc_o_c)

# AR static library archiver
quiet_cmd_ar	= AR      $(printable-target)
      cmd_ar	= $(AR) -rs $@ $? 2> /dev/null

define CreateLibrary
all-libs += $(objdir)$(1).a

$(objdir)$(1).a: $(target-objects) $(LIBS) | createdir-$(objdir)

-include $(addsuffix .cmd,$(target-objects))

$(call CreateDirectory,$(objdir))
endef

# Linker
ld_flags	= $(LDFLAGS_ALL) \
	$($(dir $(printable-target))--LDFLAGS) \
	$($(dir $(printable-target))--LDFLAGS_$(notdir $(primary_source)))

quiet_cmd_ld	= LD      $(printable-target)
      cmd_ld	= $(CC) $(ld_flags) -o $@ $(filter-out $(PHONY),$^) $($(@D)--LIBS) $($@--LIBS)

define CreateProgram
all-progs += $(objdir)$(1)

$(objdir)$(1): $(target-objects) $(LIBS) | createdir-$(objdir)

-include $(addsuffix .cmd,$(objdir)$(1) $(target-objects))

$(call CreateDirectory,$(objdir))
endef

# version string
GIT_REV := $(shell test -d .git && git describe 2> /dev/null || echo exported)
ifneq ($(GIT_REV), exported)
FULL_VERSION	:= $(patsubst v%,%,$(GIT_REV))
else
FULL_VERSION	:= $(VERSION)
endif

# include the main directory's TFbuild
include $(build-enter) TFbuild $(build-leave)

# debug dump all variables
#$(foreach VAR,$(sort $(.VARIABLES)),$(warning $(VAR)=$($(VAR))))

progs: $(all-progs)
libs: $(all-libs)

$(all-libs): %:
	$(call ExecuteCommand,ar)

$(all-progs): %: $$(call arg-check-prereq,ld)
	$(call ExecuteCommand,ld)

.PHONY: $(PHONY)
$(PHONY):

endif