aboutsummaryrefslogblamecommitdiffstats
path: root/mk/lang-c.mk
blob: a76a4c37b479a78247a9ab2ad28adeadcf391e27 (plain) (tree)
















































































































































































                                                                                                                                                                   
# Copyright (C) 2015  Mattias Andrée <maandree@member.fsf.org>
# 
# Copying and distribution of this file, with or without modification,
# are permitted in any medium without royalty provided the copyright
# notice and this notice are preserved.  This file is offered as-is,
# without any warranty.


#=== This file includes rules for C programs. ===#


# This file is ignored unless _C_STD is defined.
# _C_STD should be set the the version of C that
# is used.
# 
# If you want to compile with -pedantic, define
# the variable _PEDANTIC.
# 
# Define _CPPFLAGS with any additional CPP
# flags to use, _CFLAGS with any additional CC
# flags to use, and _LDFLAGS with any additional
# LD flags to use.
# 
# Defined in path.mk, you can change _ALL_DIRS
# if you do not want CPP definitions for all
# directories.
# 
# Define _HEADER_DIRLEVELS to specify the directory
# nesting level in src. It is assumed that all
# directories contain header files. Set to '0' if
# there are no header files.
# 
# _BIN shall list all commands to build. These
# should be the basenames. For each command
# you should be the variable _OBJ_$(COMMAND)
# that lists all objects files (without the
# suffix and without the obj/ prefix) that
# are required to build the command.


ifdef _C_STD



# WHEN TO BUILD, INSTALL, AND UNINSTALL:

cmd: cmd-c
install-cmd: install-cmd-c
uninstall: uninstall-cmd-c


# HELP VARIABLES:

# Figure out whether the GCC is being used.
ifeq ($(shell $(PRINTF) '%s\n' ${CC} | $(HEAD) -n 1),gcc)
__USING_GCC = 1
endif


# BUILD VARIABLES:

# Optimisation settings for C code compilation.
ifdef DEBUG
OPTIMISE = -Og -g
else
ifndef OPTIMISE
OPTIMISE = -O2
endif
endif

# Warning settings for C code compilation.
ifdef _PEDANTIC
_PEDANTIC = -pedantic
endif
ifdef __USING_GCC
WARN = -Wall -Wextra $(_PEDANTIC) -Wdouble-promotion -Wformat=2 -Winit-self -Wmissing-include-dirs   \
       -Wtrampolines -Wmissing-prototypes -Wmissing-declarations -Wnested-externs                    \
       -Wno-variadic-macros -Wsync-nand -Wunsafe-loop-optimizations -Wcast-align                     \
       -Wdeclaration-after-statement -Wundef -Wbad-function-cast -Wwrite-strings -Wlogical-op        \
       -Wstrict-prototypes -Wold-style-definition -Wpacked -Wvector-operation-performance            \
       -Wunsuffixed-float-constants -Wsuggest-attribute=const -Wsuggest-attribute=noreturn           \
       -Wsuggest-attribute=format -Wnormalized=nfkc -fstrict-aliasing -fipa-pure-const -ftree-vrp    \
       -fstack-usage -funsafe-loop-optimizations -Wshadow -Wredundant-decls -Winline -Wcast-qual     \
       -Wsign-conversion -Wstrict-overflow=5 -Wconversion -Wsuggest-attribute=pure -Wswitch-default  \
       -Wstrict-aliasing=1 -fstrict-overflow -Wfloat-equal -Wpadded -Waggregate-return               \
       -Wtraditional-conversion
else
WARN = -Wall -Wextra $(_PEDANTIC)
endif

# Support for internationalisation?
ifndef WITHOUT_GETTEXT
_CPPFLAGS += -D'USE_GETTEXT=1'
endif

# Add CPP definitions for all directories.
_CPPFLAGS += $(foreach D,$(_ALL_DIRS),-D'$(D)="$($(D))"')


# MORE HELP VARIABLES:

# Compilation and linking flags, and command.
__CC = $(CC) -std=$(_C_STD) $(OPTIMISE) $(WARN) $(_CPPFLAGS) $(_CFLAGS) -c
__LD = $(CC) -std=$(_C_STD) $(OPTIMISE) $(WARN) $(_LDFLAGS)
__CC_POST = $(CPPFLAGS) $(CFLAGS)
__LD_POST = $(LDFLAGS)

# Header files.
__H =
ifdef _HEADER_DIRLEVELS
ifeq ($(_HEADER_DIRLEVELS),1)
__H += src/*.h
else
ifeq ($(_HEADER_DIRLEVELS),2)
__H += src/*.h
__H += src/*/*.h
else
ifneq ($(_HEADER_DIRLEVELS),0)
__H += $(foreach W,$(shell $(SEQ) $(_HEADER_DIRLEVELS) | while read n; do $(ECHO) $$($(SEQ) $$n)" " | $(SED) 's/[^ ]* /\/\*/g'; done | $(XARGS) $(ECHO)),src$(W).h)
endif
endif
endif
endif


# BUILD RULES:

.PHONY: cmd-c
cmd-c: $(foreach B,$(_BIN),bin/$(B))

# Compile a C file into an object file.
obj/%.o: src/%.c $(__H)
	@$(PRINTF_INFO) '\e[00;01;31mCC\e[34m %s\e[00m$A\n' "$@"
	@$(MKDIR) -p $(shell dirname $@)
	$(Q)$(__CC) -o $@ $< $(__CC_POST) #$Z
	@$(ECHO_EMPTY)

# Link object files into a command.
# Dependencies are declared below..
bin/%:
	@$(PRINTF_INFO) '\e[00;01;31mLD\e[34m %s\e[00;32m$A\n' "$@"
	@$(MKDIR) -p bin
	$(Q)$(__LD) -o $@ $^ $(__LD_POST) #$Z
	@$(ECHO_EMPTY)

# Dependencies for the rule above.
$(foreach B,$(_BIN),$(foreach O,$(_OBJ_$(B)),bin/$(B): obj/$(O).o\
))


# INSTALL RULES:

.PHONY: install-cmd-c
install-cmd-c: $(foreach B,$(_BIN),bin/$(B))
	@$(PRINTF_INFO) '\e[00;01;31mINSTALL\e[34m %s\e[00m\n' "$@"
	$(Q)$(INSTALL_DIR) -- "$(DESTDIR)$(BINDIR)"
ifdef COMMAND
	$(Q)$(INSTALL_PROGRAM) $(__STRIP) $^ -- "$(DESTDIR)$(BINDIR)"
else
	$(Q)$(INSTALL_PROGRAM) $(__STRIP) $^ -- "$(DESTDIR)$(BINDIR)/$(COMMAND)"
endif
	@$(ECHO_EMPTY)


# UNINSTALL RULES:

.PHONY: uninstall-cmd-c
uninstall-cmd-c:
ifdef COMMAND
	-$(Q)$(RM) -- "$(DESTDIR)$(BINDIR)/$(COMMAND)"
else
	-$(Q)$(RM) -- $(foreach B,$(_BIN),"$(DESTDIR)$(BINDIR)/$(B)")
endif


endif