TL;DR: If you don't have anything better to do, create Makefiles by hand :) Gist here.
The other day I went back to origins with building a small C++ project. With modern tools, all went OK. However, deployment was a bit of a problem, in the sense the host had an obsolete toolchain:
Me: GCC 5.2.x, CMAKE 3.3 ...
Host: GCC 4.7.x, no CMAKE :(
So, I had to build a makefile by hand!
Following some best practices, I've devised a simple Makefile with following sections:
- A declaration section, where all parameters are specified
- A targets section, where different targets are specified (e.g. compilation, linking...)
The declaration section
Here I'm basically making the script flexible. I'm declaring:
- The compiler
- The compiler flags
- The INCLUDES
- The sources and objects
- The project (binary) name
The section looks like this:
# The compiler
CXX = /usr/bin/g++
CXXFALGS = -std=c++11 -ggdb3 -Wpedantic -Wall -Wextra \
-Wconversion -Wstrict-null-sentinel -Wold-style-cast \
-Wnoexcept -Wctor-dtor-privacy -Woverloaded-virtual \
-Wsign-promo -Wzero-as-null-pointer-constant
# Commented out (not supported by gcc<5):
# Wsuggest-final-types -Wsuggest-final-methods -Wsuggest-override
# The executable sources and target
#
INCLUDES = -I.
SRCS = main.cpp \
tests/common/checks.cpp \
tests/polynomial/test_polynomial_modulo.cpp
OBJS = $(SRCS:.cpp=.o)
MAIN = polymorph
The targets
The targets sections is as simple as possible:
- an "all" target to build the MAIN
- The compilation target (from C++ to .o)
- The linking target
- A cleanup target (if you get to copy files around like me)
It looks like this:
.PHONY: depend clean
all: $(MAIN)
@echo Polymorph binary has been compiled
$(MAIN): $(OBJS)
$(CXX) $(CXXFALGS) $(INCLUDES) -o $(MAIN) $(OBJS) $(LFLAGS) $(LIBS)
# this is a suffix replacement rule for building .o's from .c's
# it uses automatic variables $<: the name of the prerequisite of
# the rule(a .c file) and $@: the name of the target of the rule (a .o file)
# (see the gnu make manual section about automatic variables)
.cpp.o:
$(CXX) $(CXXFALGS) $(INCLUDES) -c $< -o $@
clean:
$(RM) *.o *~ $(MAIN)
depend: $(SRCS)
makedepend $(INCLUDES) $^
Please not that make is picky and you need tab indenting for targets.
Conclusion
This is a simple Makefile to build an executable. Generally, you'll need to edit the CXX , CXXFLAGS , INCLUDE , SRC and MAIN. Alternatively you can use a modern tool like CMAKE, which will create an OS-dependent makefile.
Best part is the CMAKE equivalent is much simpler:
cmake_minimum_required(VERSION 3.3)
project(polymorph)
# -Weffc++
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -std=c++14 -ggdb3 -Wpedantic -Wall -Wextra -Wconversion -Wstrict-null-sentinel -Wold-style-cast -Wnoexcept -Wctor-dtor-privacy -Woverloaded-virtual -Wsign-promo -Wzero-as-null-pointer-constant -Wsuggest-final-types -Wsuggest-final-methods -Wsuggest-override")
set(SOURCE_FILES main.cpp structures/vector.h structures/polynomial_mod.h tests/polynomial/test_polynomial_modulo.cpp tests/polynomial/test_polynomial_modulo.h tests/common/checks.cpp tests/common/checks.h)
add_executable(polymorph ${SOURCE_FILES})
HTH,
Member discussion: