xref: /haiku/data/develop/makefile-engine (revision 02354704729d38c3b078c696adc1bbbd33cbcf72)
1## Haiku Generic Makefile Engine v2.6 ##
2
3## Does all the hard work for the Generic Makefile, which only has to specify
4## the project parameters.
5
6## Supports Generic Makefile v2.6.
7##   Probably works with Generic Makefile v2.0+, but support is not guaranteed.
8
9# Determine the CPU type
10MACHINE=$(shell uname -m)
11ifeq ($(MACHINE), BePC)
12	CPU = x86
13else
14	CPU = $(MACHINE)
15endif
16
17# Set up defaults.
18ifeq ($(NAME), )
19	NAME = NameThisApp
20endif
21
22ifeq ($(TYPE), )
23	TYPE = APP
24endif
25
26ifeq ($(APP_MIME_SIG), )
27	APP_MIME = x.vnd-Haiku-$(NAME)
28endif
29
30ifeq ($(DRIVER_PATH), )
31	DRIVER_PATH = misc
32endif
33
34# Set the core tools if they're not already specified.
35MIMESET	:= mimeset
36XRES	:= xres
37RESCOMP	:= rc
38CC		:= $(CC)
39C++		:= $(CXX)
40
41# Set up CFLAGS.
42ifeq ($(strip $(TYPE)), DRIVER)
43	CFLAGS	+= -D_KERNEL_MODE=1
44else
45	CFLAGS +=
46endif
47
48# Set up optimization flags.
49ifeq ($(strip $(OPTIMIZE)), FULL)
50	OPTIMIZER	= -O3
51else
52ifeq ($(strip $(OPTIMIZE)), SOME)
53	OPTIMIZER	= -O1
54else
55ifeq ($(strip $(OPTIMIZE)), NONE)
56	OPTIMIZER	= -O0
57else
58#	OPTIMIZE isn't set, so set it to FULL
59	OPTIMIZER	= -O3
60endif
61endif
62endif
63
64# Set up debug information flags.
65ifeq ($(strip $(DEBUGGER)), TRUE)
66	DEBUG += -g
67	OPTIMIZER = -O0
68endif
69CFLAGS += $(OPTIMIZER) $(DEBUG)
70
71# Set up the warning flags.
72ifeq ($(strip $(WARNINGS)), ALL)
73	CFLAGS += -Wall -Wno-multichar -Wno-ctor-dtor-privacy
74else
75ifeq ($(strip $(WARNINGS)), NONE)
76	CFLAGS += -w
77endif
78endif
79
80# Set up the linker & linker flags.
81ifeq ($(origin LD), default)
82	LD			:= $(CC)
83endif
84LDFLAGS		+= $(DEBUG)
85
86# Binary-type-specific linker flags.
87ifeq ($(strip $(TYPE)), APP)
88	LDFLAGS += -Xlinker -soname=_APP_
89else
90ifeq ($(strip $(TYPE)), SHARED)
91	LDFLAGS += -shared -Xlinker -soname=$(NAME)
92else
93ifeq ($(strip $(TYPE)), DRIVER)
94	LDFLAGS += -nostdlib /boot/system/develop/lib/_KERNEL_ \
95				/boot/system/develop/lib/haiku_version_glue.o
96ifeq ($(CPU), x86_64)
97	LDFLAGS += -z max-page-size=0x1000
98endif
99endif
100endif
101endif
102
103# Get the compiler version.
104CC_VER = $(word 1, $(subst -, , $(subst ., , $(shell $(CC) -dumpversion))))
105
106# Set the object directory if it isn't already.
107OBJ_DIR := objects.$(CPU)-$(CC)$(CC_VER)-$(if $(DEBUGGER),debug,release)
108
109# Output the binary alongside the objects unless another directory is specified.
110ifeq ($(TARGET_DIR), )
111	TARGET_DIR	:= $(OBJ_DIR)
112endif
113
114# NOTE: make doesn't find the target if its name is enclosed in quotes.
115ifeq ($(strip $(TYPE)), STATIC)
116	TARGET		:= $(TARGET_DIR)/$(NAME).a
117else
118	TARGET		:= $(TARGET_DIR)/$(NAME)
119endif
120
121# Psuedo-function for converting a list of source files in SRCS variable to a
122# corresponding list of object files in $(OBJ_DIR)/xxx.o. The "function" strips
123# off the src file suffix (.ccp or .c or whatever) and then strips off the
124# off the directory name, leaving just the root file name. It then appends the
125# .o suffix and prepends the $(OBJ_DIR)/ path
126define SRCS_LIST_TO_OBJS
127	$(addprefix $(OBJ_DIR)/, $(addsuffix .o, $(foreach file, $(SRCS), \
128	$(basename $(notdir $(file))))))
129endef
130
131define SRCS_LIST_TO_DEPENDS
132	$(addprefix $(OBJ_DIR)/, $(addsuffix .d, $(foreach file, $(SRCS), \
133	$(basename $(notdir $(file))))))
134endef
135
136OBJS = $(SRCS_LIST_TO_OBJS)
137DEPENDS = $(SRCS_LIST_TO_DEPENDS)
138
139# Create a unique list of paths to our sourcefiles and resources.
140SRC_PATHS += $(sort $(foreach file, $(SRCS) $(RSRCS) $(RDEFS), $(dir $(file))))
141
142# Add source paths to VPATH if not already present.
143VPATH :=
144VPATH += $(addprefix :, $(subst  ,:, $(filter-out $($(subst, :, ,$(VPATH))), $(SRC_PATHS))))
145
146# Set up the local & system include paths and C++ stdlibs.
147ifneq (,$(filter $(CPU),x86 x86_64))
148	LOC_INCLUDES = $(foreach path, $(SRC_PATHS) $(LOCAL_INCLUDE_PATHS), $(addprefix -I, $(path)))
149 ifeq ($(CC_VER), 2)
150	INCLUDES = $(LOC_INCLUDES)
151	INCLUDES += -I-
152	INCLUDES += $(foreach path, $(SYSTEM_INCLUDE_PATHS), $(addprefix -I, $(path)))
153
154	STDCPPLIBS = stdc++.r4
155 else
156	INCLUDES = -iquote./
157	INCLUDES += $(foreach path, $(SRC_PATHS) $(LOCAL_INCLUDE_PATHS), $(addprefix -iquote, $(path)))
158	INCLUDES += $(foreach path, $(SYSTEM_INCLUDE_PATHS), $(addprefix -isystem, $(path)))
159
160	STDCPPLIBS = stdc++ supc++
161 endif
162else
163ifeq ($(CPU), ppc)
164	LOC_INCLUDES = $(foreach path, $(SRC_PATHS) $(LOCAL_INCLUDE_PATHS), $(addprefix -I, $(path)))
165	SYS_INCLUDES += -i-
166	SYS_INCLUDES += $(foreach path, $(SYSTEM_INCLUDE_PATHS), $(addprefix -i , $(path)))
167
168	INCLUDES = $(LOC_INCLUDES) $(SYS_INCLUDES)
169endif
170endif
171
172# Add the -L prefix to all of the library paths.
173LINK_PATHS = $(foreach path, $(SRC_PATHS) $(LIBPATHS), \
174	$(addprefix -L, $(path)))
175
176# Handle the additional libraries specified. If the libraries have a .so or
177# a .a prefix, or if they are _APP_ or _KERNEL_, simply add them to the list.
178LINK_LIBS += $(filter %.so %.a _APP_ _KERNEL_, $(LIBS))
179# If the libraries do not have suffixes and are not _APP_ or _KERNEL_,
180# prepend -l to each name:(e.g. "be" becomes "-lbe").
181LINK_LIBS += $(foreach lib, $(filter-out %.so %.a _APP_ _KERNEL_, $(LIBS)), $(addprefix -l, $(lib)))
182
183# Add the linkpaths and linklibs to LDFLAGS.
184LDFLAGS += $(LINK_PATHS)  $(LINK_LIBS)
185
186# Add the defines to CFLAGS.
187CFLAGS += $(foreach define, $(DEFINES), $(addprefix -D, $(define)))
188
189# Add the additional compiler flags to CFLAGS.
190CFLAGS += $(COMPILER_FLAGS)
191
192# Add the additional linkflags to LDFLAGS
193LDFLAGS += $(LINKER_FLAGS)
194
195# Use the archiving tools to create an an archive if we're building a static
196# library, otherwise use the linker.
197ifeq ($(strip $(TYPE)), STATIC)
198	BUILD_LINE = ar -cru "$(TARGET)" $(OBJS)
199else
200	BUILD_LINE = $(LD) -o "$@" $(OBJS) $(LDFLAGS)
201endif
202
203# Pseudo-function for converting a list of resource definition files in RDEFS
204# variable to a corresponding list of object files in $(OBJ_DIR)/xxx.rsrc.
205# The "function" strips off the rdef file suffix (.rdef) and then strips
206# of the directory name, leaving just the root file name. It then appends the
207# the .rsrc suffix and prepends the $(OBJ_DIR)/ path.
208define RDEFS_LIST_TO_RSRCS
209	$(addprefix $(OBJ_DIR)/, $(addsuffix .rsrc, $(foreach file, $(RDEFS), \
210	$(basename $(notdir $(file))))))
211endef
212
213# Create the resource definitions instruction in case RDEFS is not empty.
214ifeq ($(RDEFS), )
215	RSRCS +=
216else
217	RSRCS += $(RDEFS_LIST_TO_RSRCS)
218endif
219
220# Create the resource instruction.
221ifeq ($(RSRCS), )
222	DO_RSRCS :=
223else
224	DO_RSRCS := $(XRES) -o $(TARGET) $(RSRCS)
225endif
226
227# Set the directory for internationalization sources (catkeys) if it isn't
228# already.
229CATKEYS_DIR	:= locales
230
231# Set the directory for internationalization resource data (catalogs) if it
232# isn't already.
233CATALOGS_DIR := $(OBJ_DIR)/$(APP_MIME_SIG)
234
235# Pseudo-function for converting a list of language codes in CATALOGS variable
236# to a corresponding list of catkeys files in $(CATALOGS_DIR)/xx.catalog
237# The "function" appends the .catalog suffix and prepends the
238# $(CATALOGS_DIR)/ path.
239define LOCALES_LIST_TO_CATALOGS
240	$(addprefix $(CATALOGS_DIR)/, $(addsuffix .catalog, $(foreach lang, $(LOCALES), $(lang))))
241endef
242
243CATALOGS = $(LOCALES_LIST_TO_CATALOGS)
244
245# Define the actual work to be done.
246default: $(TARGET)
247
248$(TARGET):	$(OBJ_DIR) $(OBJS) $(RSRCS)
249	$(BUILD_LINE)
250	$(DO_RSRCS)
251	$(MIMESET) -f "$@"
252
253# Create OBJ_DIR if it doesn't exist.
254$(OBJ_DIR)::
255	@[ -d $(OBJ_DIR) ] || mkdir $(OBJ_DIR) >/dev/null 2>&1
256
257# Create the localization sources directory if it doesn't exist.
258$(CATKEYS_DIR)::
259	@[ -d $(CATKEYS_DIR) ] || mkdir $(CATKEYS_DIR) >/dev/null 2>&1
260
261# Create the localization data directory if it doesn't exist.
262$(CATALOGS_DIR):: $(OBJ_DIR)
263	@[ -d $(CATALOGS_DIR) ] || mkdir $(CATALOGS_DIR) >/dev/null 2>&1
264
265# Rules to create the dependency files.
266$(OBJ_DIR)/%.d : %.c
267	mkdir -p $(OBJ_DIR); \
268	mkdepend $(LOC_INCLUDES) -p .c:$(OBJ_DIR)/%n.o -m -f "$@" $<
269$(OBJ_DIR)/%.d : %.cpp
270	mkdir -p $(OBJ_DIR); \
271	mkdepend $(LOC_INCLUDES) -p .cpp:$(OBJ_DIR)/%n.o -m -f "$@" $<
272$(OBJ_DIR)/%.d : %.cp
273	mkdir -p $(OBJ_DIR); \
274	mkdepend $(LOC_INCLUDES) -p .cp:$(OBJ_DIR)/%n.o -m -f "$@" $<
275$(OBJ_DIR)/%.d : %.cc
276	mkdir -p $(OBJ_DIR); \
277	mkdepend $(LOC_INCLUDES) -p .cc:$(OBJ_DIR)/%n.o -m -f "$@" $<
278$(OBJ_DIR)/%.d : %.cxx
279	mkdir -p $(OBJ_DIR); \
280	mkdepend $(LOC_INCLUDES) -p .cxx:$(OBJ_DIR)/%n.o -m -f "$@" $<
281$(OBJ_DIR)/%.d : %.C
282	mkdir -p $(OBJ_DIR); \
283	mkdepend $(LOC_INCLUDES) -p .C:$(OBJ_DIR)/%n.o -m -f "$@" $<
284$(OBJ_DIR)/%.d : %.CC
285	mkdir -p $(OBJ_DIR); \
286	mkdepend $(LOC_INCLUDES) -p .CC:$(OBJ_DIR)/%n.o -m -f "$@" $<
287$(OBJ_DIR)/%.d : %.CPP
288	mkdir -p $(OBJ_DIR); \
289	mkdepend $(LOC_INCLUDES) -p .CPP:$(OBJ_DIR)/%n.o -m -f "$@" $<
290$(OBJ_DIR)/%.d : %.CXX
291	mkdir -p $(OBJ_DIR); \
292	mkdepend $(LOC_INCLUDES) -p .CXX:$(OBJ_DIR)/%n.o -m -f "$@" $<
293
294-include $(DEPENDS)
295
296# Rules to make the object files.
297$(OBJ_DIR)/%.o : %.c
298	$(CC) -c $< $(INCLUDES) $(CFLAGS) -o "$@"
299$(OBJ_DIR)/%.o : %.cpp
300	$(C++) -c $< $(INCLUDES) $(CFLAGS) -o "$@"
301$(OBJ_DIR)/%.o : %.cp
302	$(CC) -c $< $(INCLUDES) $(CFLAGS) -o "$@"
303$(OBJ_DIR)/%.o : %.cc
304	$(C++) -c $< $(INCLUDES) $(CFLAGS) -o "$@"
305$(OBJ_DIR)/%.o : %.cxx
306	$(C++) -c $< $(INCLUDES) $(CFLAGS) -o "$@"
307$(OBJ_DIR)/%.o : %.C
308	$(CC) -c $< $(INCLUDES) $(CFLAGS) -o "$@"
309$(OBJ_DIR)/%.o : %.CC
310	$(C++) -c $< $(INCLUDES) $(CFLAGS) -o "$@"
311$(OBJ_DIR)/%.o : %.CPP
312	$(C++) -c $< $(INCLUDES) $(CFLAGS) -o "$@"
313$(OBJ_DIR)/%.o : %.CXX
314	$(C++) -c $< $(INCLUDES) $(CFLAGS) -o "$@"
315
316# Rules to compile the resource definition files.
317$(OBJ_DIR)/%.rsrc : %.rdef
318	cat $< | $(CC) -E $(INCLUDES) $(CFLAGS) - | grep -av '^#' | $(RESCOMP) -I $(dir $<) -o "$@" -
319$(OBJ_DIR)/%.rsrc : %.RDEF
320	cat $< | $(CC) -E $(INCLUDES) $(CFLAGS) - | grep -av '^#' | $(RESCOMP) -I $(dir $<) -o "$@" -
321
322# Rule to compile localization data catalogs.
323$(CATALOGS_DIR)/%.catalog : $(CATKEYS_DIR)/%.catkeys
324	linkcatkeys -o "$@" -s $(APP_MIME_SIG) -l $(notdir $(basename $@)) $<
325
326# Rule to preprocess program sources into file ready for collecting catkeys.
327$(OBJ_DIR)/$(NAME).pre : $(SRCS)
328	-cat $(SRCS) | $(CC) -E -x c++ $(INCLUDES) $(CFLAGS) -DB_COLLECTING_CATKEYS - | grep -av '^#' > $(OBJ_DIR)/$(NAME).pre
329
330# Rules to collect localization catkeys.
331catkeys : $(CATKEYS_DIR)/en.catkeys
332
333$(CATKEYS_DIR)/en.catkeys : $(CATKEYS_DIR) $(OBJ_DIR)/$(NAME).pre
334	collectcatkeys -s $(APP_MIME_SIG) $(OBJ_DIR)/$(NAME).pre -o $(CATKEYS_DIR)/en.catkeys
335
336# Rule to create localization catalogs.
337catalogs : $(CATALOGS_DIR) $(CATALOGS)
338
339# Rules to handle lex/flex and yacc/bison files.
340$(OBJ_DIR)/%.o: %.l
341	flex $<
342	$(CC) -c $(INCLUDES) $(CFLAGS) lex.yy.c -o "$@"
343$(OBJ_DIR)/%.o: %.y
344	bison -d -y $<
345	$(CC) -c $(INCLUDES) $(CFLAGS) y.tab.c -o "$@"
346
347# The generic "clean" command. (Deletes everything in the object folder.)
348.PHONY: clean
349clean:
350	-rm -rf "$(OBJ_DIR)"
351
352# Remove just the application from the object folder.
353rmapp ::
354	-rm -f $(TARGET)
355
356# Make it easy to install drivers for testing.
357USER_BIN_PATH := $(shell finddir B_USER_NONPACKAGED_ADDONS_DIRECTORY)/kernel/drivers/bin
358USER_DEV_PATH := $(shell finddir B_USER_NONPACKAGED_ADDONS_DIRECTORY)/kernel/drivers/dev
359
360driverinstall :: default
361ifeq ($(strip $(TYPE)), DRIVER)
362	copyattr --data $(TARGET) $(USER_BIN_PATH)/$(NAME)
363	mkdir -p $(USER_DEV_PATH)/$(DRIVER_PATH)
364	ln -sf $(USER_BIN_PATH)/$(NAME) $(USER_DEV_PATH)/$(DRIVER_PATH)/$(NAME)
365endif
366
367install :: default
368ifeq ($(INSTALL_DIR), )
369	@echo "No install directory specified for \"$(NAME)\" (INSTALL_DIR is empty)" >&2
370else
371	mkdir -p "$(INSTALL_DIR)"
372	cp $(TARGET) "$(INSTALL_DIR)"/$(NAME)
373endif
374
375# Set the catalog installation directory if it isn't already.
376CATALOG_INSTALL_DIR := $(shell finddir B_USER_NONPACKAGED_DATA_DIRECTORY)/locale/catalogs
377
378# Rule to install localization resources catalogs.
379catalogsinstall :: catalogs
380	mkdir -p "$(CATALOG_INSTALL_DIR)/$(APP_MIME_SIG)"
381	-cp $(CATALOGS_DIR)/*.catalog "$(CATALOG_INSTALL_DIR)/$(APP_MIME_SIG)"
382
383# Alternate way of storing localization catalogs: bind them into the program
384# executable's resources.
385bindcatalogs :
386	for lc in $(LOCALES); do linkcatkeys -o $(TARGET) -s $(APP_MIME_SIG) -tr -l $$lc $(CATKEYS_DIR)/$$lc.catkeys; done
387