# Copyright (C) 2015, 2016 Mattias Andrée # # 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 aux/ prefix) that # are required to build the command. # # Binary you want installed to /sbin rather than # /bin shall be listed in _SBIN rather than in # _BIN. _SBIN and _BIN may not list binaries # with identical names. Analogically, you may # add _LIBEXEC for binary to be installed to # /libexec. # # If you only have one binary, you may select # to define _BINDIR to name the variable with # the pathname for the directory the binary # shall be installed. For example, if you want # the binary to be installed to /usr/sbin, # define _BINDIR = SBINDIR. # # List libraries to compile in in _LIB. For each # library, sould should also define # _SO_VERSION_$(LIBRARY) and _SO_MAJOR_$(LIBRARY) # with the full version number and the major # version number, respectively. ifdef _C_STD # HELP VARIABLES: # Figure out whether the GCC is being used. ifeq ($(shell $(PRINTF) '%s\n' ${CC} | $(HEAD) -n 1),gcc) __USING_GCC = 1 endif # Are there any commands? ifdef _BIN __HAVE_CMD_C = 1 endif ifdef _SBIN __HAVE_CMD_C = 1 endif ifdef _LIBEXEC __HAVE_CMD_C = 1 endif # WHEN TO BUILD, INSTALL, AND UNINSTALL: ifdef __HAVE_CMD_C cmd: cmd-c install-cmd: install-cmd-c uninstall: uninstall-cmd-c endif ifdef _LIB lib: lib-c install-lib: install-lib-c uninstall: uninstall-lib-c endif # BUILD VARIABLES: # Optimisation settings for C code compilation. ifndef OPTIMISE ifndef DEBUG OPTIMISE = -O2 -g endif ifdef DEBUG ifdef __USING_GCC OPTIMISE = -Og -g endif ifndef __USING_GCC OPTIMISE = -g endif endif endif # Warning settings for C code compilation. ifdef _PEDANTIC _PEDANTIC = -pedantic endif ifndef WARN ifndef DEBUG WARN = -Wall endif ifdef DEBUG 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 endif ifndef __USING_GCC WARN = -Wall -Wextra $(_PEDANTIC) endif endif 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))"') # Compilation and linking flags, and command. ifndef CPPFLAGS CPPFLAGS = endif ifndef CFLAGS CFLAGS = $(OPTIMISE) $(WARN) endif ifndef LDFLAGS LDFLAGS = $(OPTIMISE) $(WARN) endif __CC = $(CC) -std=$(_C_STD) -c $(_CPPFLAGS) $(_CFLAGS) __LD = $(CC) -std=$(_C_STD) $(_LDFLAGS) __CC_POST = $(CPPFLAGS) $(CFLAGS) $(EXTRA_CPPFLAGS) $(EXTRA_CFLAGS) __LD_POST = $(LDFLAGS) $(EXTRA_LDFLAGS) # Header files. __H = ifdef _HEADER_DIRLEVELS ifeq ($(_HEADER_DIRLEVELS),1) __H += src/*.h endif ifneq ($(_HEADER_DIRLEVELS),1) ifeq ($(_HEADER_DIRLEVELS),2) __H += src/*.h __H += src/*/*.h endif ifneq ($(_HEADER_DIRLEVELS),2) 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 # Directory for the binary if there is only one binary. ifndef _BINDIR _BINDIR = BINDIR endif # BUILD RULES: .PHONY: cmd-c cmd-c: $(foreach B,$(_BIN) $(_SBIN) $(_LIBEXEC)) .PHONY: lib-c lib-c: $(foreach B,$(_LIB),bin/$(B).so) # Compile a C file into an object file for a command. aux/%.o: $(v)src/%.c $(foreach H,$(__H),$(v)$(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) # Compile a C file into an object file for a library. aux/%.pic.o: $(v)src/%.c $(foreach H,$(__H),$(v)$(H)) @$(PRINTF_INFO) '\e[00;01;31mCC\e[34m %s\e[00m$A\n' "$@" @$(MKDIR) -p $(shell $(DIRNAME) $@) $(Q)$(__CC) -fPIC -o $@ $< $(__CC_POST) #$Z @$(ECHO_EMPTY) # Link object files into a library. # Dependencies are declared below. bin/%.so: @$(PRINTF_INFO) '\e[00;01;31mLD\e[34m %s\e[00;32m$A\n' "$@" @$(MKDIR) -p bin $(Q)$(__LD) -shared -Wl,-soname,$*.so.$(_SO_VERSION_$($*)) -o $@ $^ $(__LD_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. include aux/lang-c.mk aux/lang-c.mk: Makefile @$(MKDIR) -p aux @$(ECHO) > aux/lang-c.mk @$(foreach B,$(_BIN) $(_SBIN) $(_LIBEXEC),$(ECHO) bin/$(B): $(foreach O,$(_OBJ_$(B)),aux/$(O).o) >> aux/lang-c.mk &&) $(TRUE) @$(foreach B,$(_LIB),$(ECHO) bin/$(B).so: $(foreach O,$(_OBJ_$(B)),aux/$(O).pic.o) >> aux/lang-c.mk &&) $(TRUE) # INSTALL RULES: .PHONY: install-cmd-c install-cmd-c: $(foreach B,$(_BIN) $(_SBIN) $(_LIBEXEC),bin/$(B)) @$(PRINTF_INFO) '\e[00;01;31mINSTALL\e[34m %s\e[00m\n' "$@" ifndef COMMAND ifdef _BIN $(Q)$(INSTALL_DIR) -- "$(DESTDIR)$(BINDIR)" $(Q)$(INSTALL_PROGRAM) $(__STRIP) $(foreach B,$(_BIN),bin/$(B)) -- "$(DESTDIR)$(BINDIR)" endif ifdef _SBIN $(Q)$(INSTALL_DIR) -- "$(DESTDIR)$(SBINDIR)" $(Q)$(INSTALL_PROGRAM) $(__STRIP) $(foreach B,$(_SBIN),bin/$(B)) -- "$(DESTDIR)$(SBINDIR)" endif ifdef _LIBEXEC $(Q)$(INSTALL_DIR) -- "$(DESTDIR)$(LIBEXECDIR)/$(PKGNAME)" $(Q)$(INSTALL_PROGRAM) $(__STRIP) $(foreach B,$(_LIBEXEC),bin/$(B)) -- "$(DESTDIR)$(LIBEXECDIR)/$(PKGNAME)" endif endif ifdef COMMAND $(Q)$(INSTALL_DIR) -- "$(DESTDIR)$($(_BINDIR))" $(Q)$(INSTALL_PROGRAM) $(__STRIP) $^ -- "$(DESTDIR)$($(_BINDIR))/$(COMMAND)" endif @$(ECHO_EMPTY) .PHONY: install-lib-c install-lib-c: $(foreach B,$(_LIB),bin/$(B).so) @$(PRINTF_INFO) '\e[00;01;31mINSTALL\e[34m %s\e[00m\n' "$@" $(Q)$(INSTALL_DIR) -- "$(DESTDIR)$(LIBDIR)" $(Q)$(foreach B,$(_LIB),$(LN) -sf -- "$(B).so.$(_SO_VERSION_$(B))" "$(DESTDIR)$(LIBDIR)/$(B).so.$(_SO_MAJOR_$(B))" &&) $(TRUE) $(Q)$(foreach B,$(_LIB),$(INSTALL_PROGRAM) $(foreach B,$(_LIB),bin/$(B).so) -- "$(DESTDIR)$(LIBDIR)/$(B).so.$(_SO_VERSION_$(B))" &&) $(TRUE) $(Q)$(foreach B,$(_LIB),$(LN) -sf -- "$(B).so.$(_SO_VERSION_$(B))" "$(DESTDIR)$(LIBDIR)/$(B).so" &&) $(TRUE) @$(ECHO_EMPTY) # UNINSTALL RULES: .PHONY: uninstall-cmd-c uninstall-cmd-c: ifdef COMMAND -$(Q)$(RM) -- "$(DESTDIR)$($(_BINDIR))/$(COMMAND)" endif ifndef COMMAND ifdef _BIN -$(Q)$(RM) -- $(foreach B,$(_BIN),"$(DESTDIR)$(BINDIR)/$(B)") endif ifdef _SBIN -$(Q)$(RM) -- $(foreach B,$(_SBIN),"$(DESTDIR)$(SBINDIR)/$(B)") endif ifdef _LIBEXEC -$(Q)$(RM) -- $(foreach B,$(_LIBEXEC),"$(DESTDIR)$(LIBEXECDIR)/$(PKGNAME)/$(B)") -$(Q)$(RMDIR) -- "$(DESTDIR)$(LIBEXECDIR)/$(PKGNAME)" endif endif .PHONY: uninstall-lib-c uninstall-lib-c: -$(Q)$(RM) -- $(foreach B,$(_LIB),"$(DESTDIR)$(LIBDIR)/$(B).so") -$(Q)$(RM) -- $(foreach B,$(_LIB),"$(DESTDIR)$(LIBDIR)/$(B).so.$(_SO_MAJOR_$(B))") -$(Q)$(RM) -- $(foreach B,$(_LIB),"$(DESTDIR)$(LIBDIR)/$(B).so.$(_SO_VERSION_$(B))") endif # TODO install/uninstall header files