Skip to content

Instantly share code, notes, and snippets.

@je-so
Last active March 14, 2020 21:31
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save je-so/5614757 to your computer and use it in GitHub Desktop.
Save je-so/5614757 to your computer and use it in GitHub Desktop.
Generic Makefile For C Projects. Supports different building modes (Debug and Release preconfigured). Supports building mode specific configurations. C source code dependencies are computed automatically by the compiler and included into the makefile. All object files are put under directory $(TargetDir)/$(buildmode)/$(Project)/. Makefile suppor…
# Generic Makefile (c) 2013 Jörg Seebohn
# Version 1.0
# Use it at your own risk !
# This Makefile depends on GNU make.
# The clean command uses "@echo rm -rf $(TargetDir)"
# remove the echo if you know that $(TargetDir) is set to a valid value.
# The target test builds the project in Release mode and starts it.
# Adapt project specific part to your own project.
# Adapt compiler specific part to your own compiler.
# Compiler gcc is preconfigured.
# Mode specific values are added after the mode agnostic values.
# The generated binary is stored as $(TargetDir)/$(Project)_$(buildmode)
# except for the Release binary. It is named $(TargetDir)/$(Project).
# You can change the location by changing macro TargetFilename.
# The object files are stored in directory $(TargetDir)/$(buildmode)/$(Project)
# You can change the location by changing ObjectFilename
# Variable "Modes" contains the list of build modes. Add your own mode with "Modes += mymode" if you like and add
# additional compiler and linker flags with "CFlags_mymode := " and "LFlags_mymode := ".
#########################
# Project Specific Part #
#########################
Project := your_project_name
Modes := Debug Release
# Directory where target binary is created and object files
TargetDir := bin
# Search Path For Include Files (InclPaths is included before mode specific InclPaths_MODE)
InclPaths := .
InclPaths_Debug :=
InclPaths_Release :=
# Defined values used by C preprocessor (Defines is included before mode specific Defines_MODE)
Defines := CONFIG_UNITTEST=1
Defines_Debug := DEBUG
Defines_Release := RELEASE
# List of Library Names (Libs is included before mode specific Libs_MODE)
Libs :=
Libs_Debug :=
Libs_Release :=
# Search Paths for Libraries (LibPaths is included before mode specific LibPaths_MODE)
LibPaths :=
LibPaths_Debug :=
LibPaths_Release :=
# Compiler specific flags (CFlags is included before mode specific CFlags_MODE)
CFlags := -std=c99 -pedantic -Wall -Wextra -Wconversion -Wshadow -Wcast-qual -Wwrite-strings -Wstrict-prototypes -Wformat-nonliteral -Wformat-y2k
CFlags_Debug := -g
CFlags_Release := -O2
# Linker specific flags (LFlags is included before mode specific LFlags_MODE)
LFlags :=
LFlags_Debug := -g
LFlags_Release := -O2
# Add Your Source file here
# Use $(wildcard dir/*.c) if you want to include files from directory 'dir'
Src := src/test.c
Src += src/cmsg.c
##########################
# Compiler Specific Part #
##########################
IncPathFlag := -I
DefineFlag := -D
LibraryFlag := -l
LibPathFlag := -L
# -MMD flag let gcc generate a dependency file "objectfilename.d" in addition to the object file "objectfilename.o"
CC := gcc -MMD
LD := gcc
#########################
# Generic Template Part #
#########################
all: $(Modes)
clean:
@echo clean: $(Project)
@echo rm -rf $(TargetDir)
test: Release
$(call TargetFilename,Release)
$(Modes:%=clean_%):
@echo rm -rf $(TargetDir)/$(subst clean_,,$@)/$(Project)/
$(Modes:%=init_%):
@mkdir -p $(TargetDir)/$(subst init_,,$@)/$(Project)
define TargetFilename
$(TargetDir)/$(Project)$(subst _Release,,_$(1))
endef
define ObjectFilename
$(TargetDir)/$(1)/$(Project)/$(subst /,!,$(2)).o
endef
define CompileObject
$(call ObjectFilename,$(1),$(2)): $(2)
@echo cc: '$$<'
@$$(CC_$(1)) -c -o '$$@' '$$<'
endef
define TargetTemplate
CC_$(1) := $(CC) $(Defines:%=$(DefineFlag)%) $$(Defines_$(1):%=$(DefineFlag)%) $(InclPaths:%=$(IncPathFlag)%) $$(InclPaths_$(1):%=$(IncPathFlag)%) $(CFlags) $$(CFlags_$(1))
Objects_$(1) := $(foreach file,$(Src),$(call ObjectFilename,$(1),$(file)))
$(1): init_$(1) $(call TargetFilename,$(1))
$(call TargetFilename,$(1)): $$(Objects_$(1))
@echo ld: '$$@'
@$(LD) $(LFlags) $$(LFlags_$(1)) -o '$$@' $$(^:%='%') $(LibPaths:%=$(LibPathFlag)%) $$(LibPaths_$(1):%=$(LibPathFlag)%) $(Libs:%=$(LibraryFlag)%) $$(Libs_$(1):%=$(LibraryFlag)%)
$(foreach file,$(Src),$(eval $(call CompileObject,$(1),$(file))))
# Include compiler generated dependency files
-include $$(Objects_$(1):.o=.d)
endef
$(foreach mode,$(Modes),$(eval $(call TargetTemplate,$(mode))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment