Skip to content

Instantly share code, notes, and snippets.

@baedsch
Forked from maxtruxa/Makefile
Last active May 15, 2018 14:19
Show Gist options
  • Select an option

  • Save baedsch/eda761a3ba00627b8ae477e50550d32f to your computer and use it in GitHub Desktop.

Select an option

Save baedsch/eda761a3ba00627b8ae477e50550d32f to your computer and use it in GitHub Desktop.
Generic makefile for C/C++ with automatic dependency generation, support for deep source file hierarchies and custom intermediate directories. In addition, a setup with multiple test files (e.g. boost test) and mutliple source files containing main() functions is possible.
# output binary
TESTBIN := test1 test2
BIN := main
# sourcefiles containing main()
MAINSRCS := test/test1.cpp test/test2.cpp src/main.cpp
# library source files
LIBSRCS := src/file1.cpp src/file2.cpp ...
#source files
SRCS := $(MAINSRCS) $(LIBSRCS)
# files included in the tarball generated by 'make dist' (e.g. add LICENSE file)
DISTFILES := $(BIN)
# filename of the tar archive generated by 'make dist'
DISTOUTPUT := $(BIN).tar.gz
# intermediate directory for generated object files
OBJDIR := .o
# intermediate directory for generated dependency files
DEPDIR := .d
# library object files, auto generated from source files
LIBOBJS := $(patsubst %,$(OBJDIR)/%.o,$(basename $(LIBSRCS)))
# object files, auto generated from source files
OBJS := $(patsubst %,$(OBJDIR)/%.o,$(basename $(SRCS)))
# dependency files, auto generated from source files
DEPS := $(patsubst %,$(DEPDIR)/%.d,$(basename $(SRCS)))
# compilers (at least gcc and clang) don't create the subdirectories automatically
$(shell mkdir -p $(dir $(OBJS)) >/dev/null)
$(shell mkdir -p $(dir $(DEPS)) >/dev/null)
# C compiler
CC := gcc
# C++ compiler
CXX := g++
# linker
LD := g++
# tar
TAR := tar
# C flags
CFLAGS := -std=c14
# C++ flags
CXXFLAGS := -std=c++14
# C/C++ flags
CPPFLAGS := -g -Wall -Wextra -pedantic
# linker flags
LDFLAGS :=
# flags required for dependency generation; passed to compilers
DEPFLAGS = -MT $@ -MD -MP -MF $(DEPDIR)/$*.Td
# compile C source files
COMPILE.c = $(CC) $(DEPFLAGS) $(CFLAGS) $(CPPFLAGS) -c -o $@
# compile C++ source files
COMPILE.cc = $(CXX) $(DEPFLAGS) $(CXXFLAGS) $(CPPFLAGS) -c -o $@
# link object files to binary
LINK.o = $(LD) $(LDFLAGS) $(LDLIBS) -o $@
# precompile step
PRECOMPILE =
# postcompile step
POSTCOMPILE = mv -f $(DEPDIR)/$*.Td $(DEPDIR)/$*.d
all: $(BIN)
dist: $(DISTFILES)
$(TAR) -cvzf $(DISTOUTPUT) $^
.PHONY: clean
clean:
$(RM) -r $(OBJDIR) $(DEPDIR)
.PHONY: distclean
distclean: clean
$(RM) $(BIN) $(DISTOUTPUT)
.PHONY: install
install:
@echo no install tasks configured
.PHONY: uninstall
uninstall:
@echo no uninstall tasks configured
.PHONY: check
check:
@echo no tests configured
.PHONY: help
help:
@echo available targets: all dist clean distclean install uninstall check
$(TESTBIN): %: .o/test/%.o $(LIBOBJS)
$(LINK.o) $^
$(BIN): %: .o/src/%.o $(LIBOBJS)
$(LINK.o) $^
$(OBJDIR)/%.o: %.c
$(OBJDIR)/%.o: %.c $(DEPDIR)/%.d
$(PRECOMPILE)
$(COMPILE.c) $<
$(POSTCOMPILE)
$(OBJDIR)/%.o: %.cpp
$(OBJDIR)/%.o: %.cpp $(DEPDIR)/%.d
$(PRECOMPILE)
$(COMPILE.cc) $<
$(POSTCOMPILE)
$(OBJDIR)/%.o: %.cc
$(OBJDIR)/%.o: %.cc $(DEPDIR)/%.d
$(PRECOMPILE)
$(COMPILE.cc) $<
$(POSTCOMPILE)
$(OBJDIR)/%.o: %.cxx
$(OBJDIR)/%.o: %.cxx $(DEPDIR)/%.d
$(PRECOMPILE)
$(COMPILE.cc) $<
$(POSTCOMPILE)
.PRECIOUS = $(DEPDIR)/%.d
$(DEPDIR)/%.d: ;
-include $(DEPS)
#include <iostream>
int main() {
std::cout << "Hello, World!\n";
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment