Universal simple Makefile

I often work on my netbook, so I prefer to use Sublime Text with Makefiles instead of full-featured IDEs. To automate build process I’ve constructed (with help of Vasily Picard and examples from the Internet) universal Makefile. It assumes the following structure of files.

All sources are placed in the src subdirectory. Intermediate object files are placed in obj subdirectory, it must be created before compilation. Resulting binary file is placed into bin subdirectory. If you use gengetopt as command-line arguments parcer, name ggo file as cmdline.ggo and *.c and *.h files will be updated automatically if ggo is changed.

The following makefile is set to use mpi compilers, include OpenGL, CUDA and GLUT libraries, and compile CUDA source code as well. Feel free to remove unnecessary fragments and to change application binary name (in the first line).

APPNAME := bin/app
SOURCES := $(wildcard src/*.cpp src/*.cu src/*.c)
OBJECTS := $(patsubst src%,obj%, $(patsubst %.cu,%.device.o, $(patsubst %.cpp,%.o, $(patsubst %.c,%.o, $(SOURCES)))))

INCLUDE := -I/usr/local/cuda/include
LIBPATH := -L/usr/local/cuda/lib64
LIBS    := -lcudart -lGL -lglut

FLAGS    := -O3 -ffast-math -Wall -Werror -fopenmp
CCFLAGS  := $(FLAGS)
CXXFLAGS := $(FLAGS) -std=c++0x

GENCODE_FLAGS := -gencode arch=compute_20,code=sm_20 -gencode arch=compute_30,code=sm_30 -gencode arch=compute_35,code=sm_35
NVCCFLAGS     := $(GENCODE_FLAGS) --compiler-options -fno-strict-aliasing -lineinfo -use_fast_math -Xptxas -dlcm=cg

CC   := mpicc
CXX  := mpicxx
NVCC := /usr/local/cuda/bin/nvcc

all: $(OBJECTS)
	$(CXX) $(CXXFLAGS) $(INCLUDE) $(OBJECTS) -o $(APPNAME) $(LIBPATH) $(LIBS)

obj/cmdline.o: src/cmdline.c
	$(CC) -Wno-unused-but-set-variable -c $< -o $@

src/cmdline.c: src/cmdline.ggo
	gengetopt --input=src/cmdline.ggo --output-dir=src --include-getopt

%.o: ../src/%.c
	$(CC) $(CCFLAGS) $(INCLUDE) -c $< -o $@

%.o: ../src/%.cpp
	$(CXX) $(CXXFLAGS) $(INCLUDE) -c $< -o $@

%.device.o: ../src/%.cu
	$(NVCC) $(NVCCFLAGS) -c $< -o $@

clean:
	rm -rf obj/*
	rm -f $(APPNAME)