haiku/data/develop/makefile-engine
Siarzhuk Zharski 4142f7dcef A workaround for compatibility problem, originated from r40300 changes.
Proposed in it "LD ?= gcc" assignment doesn't works both with existing
makefiles and with current version of the makefile template. User must 
define LD in it's makefile to let them work. That is bad.

This workaround uses $origin function to check for redefinition of LD
variable in user's makefile.



git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@40739 a95241bf-73f2-0310-859d-f6bbb57e9c96
2011-02-28 19:17:55 +00:00

319 lines
9.0 KiB
Plaintext

## BeOS and Haiku Generic Makefile Engine v2.2.0
## Does all the hard work for the Generic Makefile
## which simply defines the project parameters
## Supports Generic Makefile v2.0, 2.01, 2.1, 2.2, 2.3
# determine wheather running on x86 or ppc
MACHINE=$(shell uname -m)
ifeq ($(MACHINE), BePC)
CPU = x86
else
CPU = $(MACHINE)
endif
# create some default settings
ifeq ($(NAME), )
NAME = NameThisApp
endif
ifeq ($(TYPE), )
TYPE = APP
endif
ifeq ($(DRIVER_PATH), )
DRIVER_PATH = misc
endif
# specify the mimeset tool
MIMESET := mimeset
# specify the tools for adding and removing resources
XRES := xres
# specify the tools for compiling resource definition files
RESCOMP := rc
# set the compiler and compiler flags
CC := gcc
C++ := g++
# SETTING: set the CFLAGS for each binary type
ifeq ($(TYPE), DRIVER)
CFLAGS += -D_KERNEL_MODE=1 -no-fpic
else
CFLAGS +=
endif
# SETTING: set the proper optimization level
ifeq ($(OPTIMIZE), FULL)
OPTIMIZER = -O3
else
ifeq ($(OPTIMIZE), SOME)
OPTIMIZER = -O1
else
ifeq ($(OPTIMIZE), NONE)
OPTIMIZER = -O0
else
# OPTIMIZE not set so set to full
OPTIMIZER = -O3
endif
endif
endif
# SETTING: set proper debugger flags
ifeq ($(DEBUGGER), TRUE)
DEBUG += -g
OPTIMIZER = -O0
endif
CFLAGS += $(OPTIMIZER) $(DEBUG)
# SETTING: set warning level
ifeq ($(WARNINGS), ALL)
CFLAGS += -Wall -Wno-multichar -Wno-ctor-dtor-privacy
else
ifeq ($(WARNINGS), NONE)
CFLAGS += -w
endif
endif
# set the linker and linker flags
ifeq ($(origin LD), default)
LD := gcc
endif
LDFLAGS += $(DEBUG)
# SETTING: set linker flags for each binary type
ifeq ($(TYPE), APP)
LDFLAGS += -Xlinker -soname=_APP_
else
ifeq ($(TYPE), SHARED)
LDFLAGS += -nostart -Xlinker -soname=$(NAME)
else
ifeq ($(TYPE), DRIVER)
LDFLAGS += -nostdlib /boot/develop/lib/x86/_KERNEL_ \
/boot/develop/lib/x86/haiku_version_glue.o
endif
endif
endif
# guess compiler version
CC_VER = $(word 1, $(subst -, , $(subst ., , $(shell $(CC) -dumpversion))))
# set the directory where object files and binaries will be created
OBJ_DIR := objects.$(CPU)-$(CC)$(CC_VER)-$(if $(DEBUGGER),debug,release)
# specify the directory the binary should be created in by default
ifeq ($(TARGET_DIR), )
TARGET_DIR := $(OBJ_DIR)
endif
# NOTE: make doesn't find the target if its name is enclosed in
# quotation marks
TARGET := $(TARGET_DIR)/$(NAME)
# psuedo-function for converting a list of source files in SRCS variable
# to a corresponding list of object files in $(OBJ_DIR)/xxx.o
# The "function" strips off the src file suffix (.ccp or .c or whatever)
# and then strips of the directory name, leaving just the root file name.
# It then appends the .o suffix and prepends the $(OBJ_DIR)/ path
define SRCS_LIST_TO_OBJS
$(addprefix $(OBJ_DIR)/, $(addsuffix .o, $(foreach file, $(SRCS), \
$(basename $(notdir $(file))))))
endef
define SRCS_LIST_TO_DEPENDS
$(addprefix $(OBJ_DIR)/, $(addsuffix .d, $(foreach file, $(SRCS), \
$(basename $(notdir $(file))))))
endef
OBJS = $(SRCS_LIST_TO_OBJS)
DEPENDS = $(SRCS_LIST_TO_DEPENDS)
# create a unique list of paths to our sourcefiles
SRC_PATHS += $(sort $(foreach file, $(SRCS), $(dir $(file))))
# add source paths to VPATH if not already present
VPATH :=
VPATH += $(addprefix :, $(subst ,:, $(filter-out $($(subst, :, ,$(VPATH))), $(SRC_PATHS))))
# SETTING: build the local and system include paths
ifeq ($(CPU), x86)
LOC_INCLUDES = $(foreach path, $(SRC_PATHS) $(LOCAL_INCLUDE_PATHS), $(addprefix -I, $(path)))
ifeq ($(CC_VER), 2)
INCLUDES = $(LOC_INCLUDES)
INCLUDES += -I-
INCLUDES += $(foreach path, $(SYSTEM_INCLUDE_PATHS), $(addprefix -I, $(path)))
else
INCLUDES = -iquote./
INCLUDES += $(foreach path, $(SRC_PATHS) $(LOCAL_INCLUDE_PATHS), $(addprefix -iquote, $(path)))
INCLUDES += $(foreach path, $(SYSTEM_INCLUDE_PATHS), $(addprefix -isystem, $(path)))
endif
else
ifeq ($(CPU), ppc)
LOC_INCLUDES = $(foreach path, $(SRC_PATHS) $(LOCAL_INCLUDE_PATHS), $(addprefix -I, $(path)))
SYS_INCLUDES += -i-
SYS_INCLUDES += $(foreach path, $(SYSTEM_INCLUDE_PATHS), $(addprefix -i , $(path)))
INCLUDES = $(LOC_INCLUDES) $(SYS_INCLUDES)
endif
endif
# SETTING: add the -L prefix to all library paths to search
LINK_PATHS = $(foreach path, $(SRC_PATHS) $(LIBPATHS), \
$(addprefix -L, $(path)))
# SETTING: specify the additional libraries to link against
# if the libraries have a .so or .a prefix, or if they are _APP_ or _KERNEL_
# simply add them to the list
LINK_LIBS += $(filter %.so %.a _APP_ _KERNEL_, $(LIBS))
# if the libraries do not have suffixes and are not _APP_ or _KERNEL_
# prepend -l to each name: be becomes -lbe
LINK_LIBS += $(foreach lib, $(filter-out %.so %.a _APP_ _KERNEL_, $(LIBS)), $(addprefix -l, $(lib)))
# add to the linker flags
LDFLAGS += $(LINK_PATHS) $(LINK_LIBS)
# SETTING: add the defines to the compiler flags
CFLAGS += $(foreach define, $(DEFINES), $(addprefix -D, $(define)))
# SETTING: add the additional compiler flags
CFLAGS += $(COMPILER_FLAGS)
# SETTING: add the additional linker flags
LDFLAGS += $(LINKER_FLAGS)
# SETTING: use the archive tools if building a static library
# otherwise use the linker
ifeq ($(TYPE), STATIC)
BUILD_LINE = ar -cru "$(TARGET)" $(OBJS)
else
BUILD_LINE = $(LD) -o "$@" $(OBJS) $(LDFLAGS)
endif
# pseudo-function for converting a list of resource definition files in RDEFS
# variable to a corresponding list of object files in $(OBJ_DIR)/xxx.rsrc
# The "function" strips off the rdef file suffix (.rdef) and then strips
# of the directory name, leaving just the root file name.
# It then appends the .rsrc suffix and prepends the $(OBJ_DIR)/ path
define RDEFS_LIST_TO_RSRCS
$(addprefix $(OBJ_DIR)/, $(addsuffix .rsrc, $(foreach file, $(RDEFS), \
$(basename $(notdir $(file))))))
endef
# create the resource definitions instruction in case RDEFS is not empty
ifeq ($(RDEFS), )
RSRCS +=
else
RSRCS += $(RDEFS_LIST_TO_RSRCS)
endif
# create the resource instruction
ifeq ($(RSRCS), )
DO_RSRCS :=
else
DO_RSRCS := $(XRES) -o $(TARGET) $(RSRCS)
endif
# define the actual work to be done
default: $(TARGET)
$(TARGET): $(OBJ_DIR) $(OBJS) $(RSRCS)
$(BUILD_LINE)
$(DO_RSRCS)
$(MIMESET) -f "$@"
# rule to create the object file directory if needed
$(OBJ_DIR)::
@[ -d $(OBJ_DIR) ] || mkdir $(OBJ_DIR) > /dev/null 2>&1
# rules to make the dependency files
$(OBJ_DIR)/%.d : %.c
[ -d $(OBJ_DIR) ] || mkdir $(OBJ_DIR) > /dev/null 2>&1; \
mkdepend $(LOC_INCLUDES) -p .c:$(OBJ_DIR)/%n.o -m -f "$@" $<
$(OBJ_DIR)/%.d : %.cpp
[ -d $(OBJ_DIR) ] || mkdir $(OBJ_DIR) > /dev/null 2>&1; \
mkdepend $(LOC_INCLUDES) -p .cpp:$(OBJ_DIR)/%n.o -m -f "$@" $<
$(OBJ_DIR)/%.d : %.cp
[ -d $(OBJ_DIR) ] || mkdir $(OBJ_DIR) > /dev/null 2>&1; \
mkdepend $(LOC_INCLUDES) -p .cp:$(OBJ_DIR)/%n.o -m -f "$@" $<
$(OBJ_DIR)/%.d : %.cc
[ -d $(OBJ_DIR) ] || mkdir $(OBJ_DIR) > /dev/null 2>&1; \
mkdepend $(LOC_INCLUDES) -p .cc:$(OBJ_DIR)/%n.o -m -f "$@" $<
$(OBJ_DIR)/%.d : %.C
[ -d $(OBJ_DIR) ] || mkdir $(OBJ_DIR) > /dev/null 2>&1; \
mkdepend $(LOC_INCLUDES) -p .C:$(OBJ_DIR)/%n.o -m -f "$@" $<
$(OBJ_DIR)/%.d : %.CC
[ -d $(OBJ_DIR) ] || mkdir $(OBJ_DIR) > /dev/null 2>&1; \
mkdepend $(LOC_INCLUDES) -p .CC:$(OBJ_DIR)/%n.o -m -f "$@" $<
$(OBJ_DIR)/%.d : %.CPP
[ -d $(OBJ_DIR) ] || mkdir $(OBJ_DIR) > /dev/null 2>&1; \
mkdepend $(LOC_INCLUDES) -p .CPP:$(OBJ_DIR)/%n.o -m -f "$@" $<
-include $(DEPENDS)
# rules to make the object files
$(OBJ_DIR)/%.o : %.c
$(CC) -c $< $(INCLUDES) $(CFLAGS) -o "$@"
$(OBJ_DIR)/%.o : %.cpp
$(C++) -c $< $(INCLUDES) $(CFLAGS) -o "$@"
$(OBJ_DIR)/%.o : %.cp
$(CC) -c $< $(INCLUDES) $(CFLAGS) -o "$@"
$(OBJ_DIR)/%.o : %.cc
$(C++) -c $< $(INCLUDES) $(CFLAGS) -o "$@"
$(OBJ_DIR)/%.o : %.C
$(CC) -c $< $(INCLUDES) $(CFLAGS) -o "$@"
$(OBJ_DIR)/%.o : %.CC
$(C++) -c $< $(INCLUDES) $(CFLAGS) -o "$@"
$(OBJ_DIR)/%.o : %.CPP
$(C++) -c $< $(INCLUDES) $(CFLAGS) -o "$@"
# rules to compile resource definition files
$(OBJ_DIR)/%.rsrc : %.rdef
cat $< | $(CC) -E $(INCLUDES) $(CFLAGS) - | grep -v '^#' | $(RESCOMP) -I $(dir $<) -o "$@" -
$(OBJ_DIR)/%.rsrc : %.RDEF
cat $< | $(CC) -E $(INCLUDES) $(CFLAGS) - | grep -v '^#' | $(RESCOMP) -I $(dir $<) -o "$@" -
# rules to handle lex/flex and yacc/bison files
$(OBJ_DIR)/%.o: %.l
flex $<
$(CC) -c $(INCLUDES) $(CFLAGS) lex.yy.c -o "$@"
$(OBJ_DIR)/%.o: %.y
bison -d -y $<
$(CC) -c $(INCLUDES) $(CFLAGS) y.tab.c -o "$@"
# empty rule. Things that depend on this rule will always get triggered
FORCE:
# The generic clean command. Delete everything in the object folder.
clean :: FORCE
-rm -rf "$(OBJ_DIR)"
# remove just the application from the object folder
rmapp ::
-rm -f $(TARGET)
# make it easy to install drivers for testing
USER_BIN_PATH = /boot/home/config/add-ons/kernel/drivers/bin
USER_DEV_PATH = /boot/home/config/add-ons/kernel/drivers/dev
driverinstall :: default
ifeq ($(TYPE), DRIVER)
copyattr --data $(TARGET) $(USER_BIN_PATH)/$(NAME)
mkdir -p $(USER_DEV_PATH)/$(DRIVER_PATH)
ln -sf $(USER_BIN_PATH)/$(NAME) $(USER_DEV_PATH)/$(DRIVER_PATH)/$(NAME)
endif
install :: default
ifeq ($(INSTALL_DIR), )
@echo "No install directory specified for \"$(NAME)\" (INSTALL_DIR is empty)" >&2
else
mkdir -p "$(INSTALL_DIR)"
cp $(TARGET) $(INSTALL_DIR)/$(NAME)
endif