makefile: how to specify header files - c++

I'm trying to write a makefile for all of my cpp prjects. After searching from the internet, I make a makefile as below:
g++11=g++ -std=c++11 -stdlib=libc++
CPPFILES=$(wildcard *.cpp)
OBJFILES=$(CPPFILES:.cpp=.o)
res.out: $(OBJFILES)
$(g++11) -lncurses -o $# $^ -g
#obj/%.o: %.cpp
%.o: %.cpp
$(g++11) -c -o $# $< -g
clean:
rm *.o *.out
I tried to use this file to compile my cpp projects and it worked well.
However, when I make some change in the header files, it doesn't work anymore because this makefile can't detect the modification in header files.
Is there any easy way to specify header files in the makefile?
Ofc I don't want to specify them one by one.

First of all, you should understand the concept of make.
Make is not only for compiling C++, it's a universal tool where a product (file) is built from other files. When you issue the make, it checks whether the top product should be rebuilt, based on the file change dates of dependencies. If rebuild is needed, first checks all the dependencies whether they should be rebuild... and so on. These bricks are called rules.
This is a rule:
target: dependency1 dependency2 ...
command1 to produce targets
command2
In case of a CPP project:
myapp: myapp.cpp myapp.hpp
g++ myapp.cpp -o myapp
More info: http://www.cs.cmu.edu/~gkesden/412-18/fall01/projects/proj1/make/makeintro.html

Related

Makefile with multiple separate *.cpp files to output separate *.exe files in different dir

I am stuck, writing my Makefile.
Directory structure:
.\
Makefile
.\src\*.cpp(s)
.\bin
Desire: What I want to achieve with one Makefile.
Run: make
Output (Terminal):
g++ -g -Wall -c -o src/program1.o src/program1.cpp
g++ -g -Wall -c -o src/program2.o src/program2.cpp
g++ -g -Wall -c -o src/program3.o src/program3.cpp
g++ -g -Wall -c -o src/program4.o src/program4.cpp
Output (in /bin/)
program1.exe
program2.exe
program3.exe
program4.exe
EDIT:
CXX = g++
CXXFLAGS = -Wall -g3 -O0
SRC := ${wildcard src/*.cpp}
OBJS := $(SRC:.cpp=.o)
BIN := $(SRC:src/%.cpp=bin/%)
.PHONY: all
all: $(BIN)
$(BIN): $(OBJS)
$(CXX) -c $(CXXFLAGS) -o $(OBJS)
bin/%: src/%.o
$(CXX) -o $# $^
Error:
g++: warning: linker input file unused because linking not done
The introductory parts of the GNU make manual describe that all: $(BIN) creates a target all that depends on a target bin. That means make will try to create bin. Then you have $(BIN): $(OBJS) which says bin depends on all the object files, so make will try to create all the object files. Then there's a recipe for that rule that says, after you've created the object files run this command, which links together all the object files into a single program (bin).
So make is doing exactly what you asked it to do.
The problem is that is apparently not what you want it to do.
In your question you write, then take the original filenames of each *.cpp and add that to the executable which I don't fully understand, but I assumed that you want to link all the objects into a single executable, which is what your makefile does.
But then later you write: How can I output to bin directory and generate the correct executables?, but you never define what "correct executables" means, and this makes it sound like you want to turn each individual object file into its own executable; that's clearly not what your makefile does.
So before you can tell make what you want, first you have understand clearly what you want so you can write it in your makefile. And if you need us to help you write it into your makefile, you need to explain it clearly in your question so we can understand it.
Cheers!
ETA
OK so you want every source file to compile into an object file, then every object file to compile to a separate binary.
First compute the names of all the binaries you want to build:
SRCS := $(wildcard src/*.cpp)
BINS := $(SRCS:src/%.cpp=bin/%)
Now make a rule that depends on all the binaries:
all: $(BINS)
Now make a pattern rule that tells make how to build each one of those binaries:
bin/% : src/%.o
$(CXX) $(CXXFLAGS) -o $# $^ $(LDLIBS)
Now you're actually done, because make already has a built-in rule that knows how to build a .o file into the same directory where the .c file lives, so it can figure out how to build the src/x.o files on its own.
Try something like:
SRC:=${wildcard src/*.cpp}
OBJ:=$(patsubst %.cpp,%.o,${patsubst src/%,bin/%,${SRC}}}
to get the list of the object files, and the rule:
obj/%.o : src/%.cpp
${CXX} -o $# -c $<
for compiling into the right location.
EDIT You have now clarified that each file is a separate main.
SRC:=${wildcard src/*.cpp}
BIN:=$(patsubst %.cpp,,${patsubst src/%,bin/%,${SRC}}}
to get the list of the object files, and the rule:
bin/% : src/%.cpp
${CXX} -o $# $<
will write each output as an executable in bin. To kick it off:
all : ${BIN}

Why does GNU make always re-link my project?

I have the following Makefile in a directory full of .cpp and .h files:
CFLAGS=-g -std=c++0x -Wall -pedantic -Wextra -D __STDC_LIMIT_MACROS -D __STDC_FORMAT_MACROS -O0
CXX=g++
LDFLAGS=-lgmp -lmathsat -lz3
all: Foo.o Bar.o
$(CXX) $(CFLAGS) -o myexe Foo.o Bar.o $(LDFLAGS)
depend: .depend
.depend: $(wildcard *.cpp)
rm -f ./.depend
$(CXX) $(CFLAGS) -MM $^ > ./.depend
include .depend
%.o: %.cpp
$(CXX) $(CFLAGS) $(INCLUDE) $< -c
clean:
rm -f *.o myexe
When I hit make, it invariably executes the last step (linking) even when none of the .o files have changed. How can I prevent make from doing that? I'd expect make to output Everything up-to-date or something similar.
I'm on a i686 GNU/Linux machine with GNU Make 3.82 and g++ version 4.8.2.
Make relinks your project because it tries to build all. The rule for all does not create any file named all. Instead it produces myexe. Next time you run make, it will see that there's no all, but there's a rule to build one, so it dutifully executes that rule which happens to link myexe every time you run make.
In order to fix your problem you need to change your makefile to look roughly like this:
all: myexe
echo Build done
myexe: <myexe dependencies go here>
$(CXX) $(CFLAGS) -o myexe $(wildcard *.o) $(LDFLAGS)
Make always tries to build the top rule. For you, this is all. Since your all rule doesn't actually make an all file it will always be run.
Your probably want your all rule to be a myexe rule and, if you want an explicit all rule, have a dependency only rule: all: myexe.
(With GNU Make, you might want to explicitly declare those targets which aren't supposed to generate a real file with a .PHONY rule. e.g. .PHONY: all depend clean.)
make is a rule-based expert system.
You give it a heap of rules and a target (default target is the first one listed), and then it builds a complete dependency tree.
All parts are rebuilt iff they are non-existent resp. older than their dependencies, recursively.
The rule you are stumbling over is this: Because the target all does not create an output file all, make invokes the non-existent-or-outdated rule.
You can correct this by making the target all not do any work but instead just depend on the output file. Marking it .PHONY is also a good idea.

How to include a makefile into an other makefile?

I have some C++ classes, every one into his own folder with a makefile, test.cpp for testing purpose, etc.
Main folder
|-> Class1 folder
|-> Class2 folder
|-> Class2.1 folder
|-> Class2 folder
I have a main project, that must include these classes. I am trying to include all sub-makefiles into the main makefile.
I have tried with "INCLUDE POO/makefile", but this solution has 2 problems:
The path of the sub-makefiles is incorrect, so files are not found ("There is not rule to build the target 'Vector3D.cpp'").
The "test.cpp" file is overrided, probably because of the path problem.("warning: overriding recipe for target ...")
I would like all makefile independent, so I can copy/paste the class folder into a new project and it still working, or I may exec the makefile alone without changes on it.
So the question is: How to include (correctly) a makefile into another makefile?
Example, just for test purpose.
Main makefile (simplified)
include Vector3D/makefile
include Color/makefile
CPP = g++
CXXFLAGS = $(CXXINCS) -Wall -O0
all: main
main: main.o Vector3D.o Color.o
$(CPP) main.o Vector3D.o Color.o -o main
main.o: main.cpp
$(CPP) -c main.cpp -o main.o $(CXXFLAGS)
Sub-makefile example (simplified)
#Vector3D
CPP = g++
CXXFLAGS = $(CXXINCS) -Wall -O0
all: test
test: Vector3D.o test.o
$(CPP) Vector3D.o test.o -o test
Vector3D/test.o: test.cpp
$(CPP) -c test.cpp -o test.o $(CXXFLAGS)
Vector3D.o: Vector3D.cpp Vector3D.hpp
$(CPP) -c Vector3D.cpp -o Vector3D.o $(CXXFLAGS)
Similar for Color/makefile than Vector3D.
I would like all makefile independent, so I may copy/past the class folder into a new project and it still working, or I may exec the makefile alone without changes on it.
I'm pretty sure that's not possible. Your makefiles either need to be standalone, in which case you can make the top-level files invoke make in lower level directories recursively (so do not include them) or you can have a single non-recursive makefile formed by including other makefiles. I don't think it's possible to do both.
How to include (correctly) a makefile into an other makefile?
The only valid answer is "using the include directive" (other than the usual "it depends".) Any other advice depends on the structure of the makefiles. Makefiles designed to be included will obviously be easier to include. Just including some random makefile and hoping it will work ... won't work. Check out Implementing non-recursive make and Boilermake for how to make non-recursive makefiles work.
Note that there's no need to include them at the top of the file and doing so may be a bad idea, as the default target becomes the first one in the included file.
Thanks to #Jonathan-wakely to provide the initial concepts for this solution.
There are probably many things that may be improved, but it works.
Requirements summary:
Makefiles should work standalone
The main makefile will includes sub-makefiles
No conflicts or path problem should appear.
A simple solution is to call recursively makefiles:
Create a "normal" script for leaf makefiles
Using an empty target allow to execute always make calls for example "sub-make:" without any requirement after ":"
Use the "-C" parameter to set the root directory for the make call.
Create the final linking with binaries created by sub-makefiles.
Example for the main makefile:
#all make recursive calls
sub-make:
make -C Vector3D
make -C Color
#final linking
CPP = g++
FLAGS = $(CXXINCS) -Wall -O0
all: main
main: main.o Vector3D/Vector3D.o Color/Color.o
$(CPP) main.o Vector3D/Vector3D.o Color/Color.o -o main
main.o: main.cpp
$(CPP) -c main.cpp -o main.o $(FLAGS)
There is probably a better way to provide *.o binaries to the linker without writing all full path, but that is another problem.
Creating the clean target. For leaf makefiles, there are no special considerations to take, but for the main makefile, it must call sub-clean rules.
clean:
make -C Vector3D clean
make -C Color clean
rm -f *.o main
EDITING:
Here is the makefile structure I have done, for if it may be useful to anyone.
To work, All classes must be in it own folder with:
.hpp header
.cpp code
main.cpp for testing
Required classes (LIBS) directory are specified with "$(LIBSPATH)LibName" in relation to this makefile.
Makefile
#Following configuration may be set with a parameter:
# e.g: make FLAGS="-Wall -O0"
FLAGS = $(CXXINCS) -Wall -O0
#Configurable variables
EXEC = main
CLASS = World
LIBS = Color Vector3D Triangle
LIBSPATH = ../
#Static content
CPP = g++
OBJS = $(foreach dir, $(LIBS), $(LIBSPATH)$(dir)/$(dir))
all: $(EXEC)
clean:
rm -f *.o $(EXEC)
$(foreach dir,$(LIBS),make clean --no-print-directory -C $(LIBSPATH)$(dir);)
$(EXEC): $(CLASS).o $(EXEC).o $(OBJS:=.o)
$(CPP) $(CLASS).o $(OBJS:=.o) $(EXEC).o -o $(EXEC)
$(EXEC).o: $(EXEC).cpp
$(CPP) -c $(EXEC).cpp -o $(EXEC).o $(CXXFLAGS)
$(CLASS).o: $(CLASS).cpp $(CLASS).hpp
$(CPP) -c $(CLASS).cpp -o $(CLASS).o $(CXXFLAGS)
$(OBJS:=.o): $(OBJS:=.cpp) $(OBJS:=.hpp)
make --no-print-directory -C $(LIBSPATH)$(strip $(foreach dir,$(LIBS),$(if $(findstring $(dir),$#),$(dir))))

beginner GNU Makefile Error

This is my first, attempt at a, Makefile after necessity from a previous post.
Anyway here's the code
SortLab.exe : SelectionSort.o Main.o
g++ -o $# $^
SelectionSort.o : SelectionSort.cpp SelectionSort.h
Main.o : Main.cpp
#-------------------------------------------------------------
run: SortLab.exe
./SortLab.exe
clean:
rm -f *.o
rm -f *.exe
build: clean SortLab.exe
%.o: %.cpp
g++ -c $<
I intend to have SelectionSort.cpp & SelectionSort.h form an object file, and Main.cpp to form its own object file. Then finally create an executable. Main.cpp depends on SelectionSort.cpp, where do I go wrong?
Also where can I find what the different GNU commands mean, -o -c and such
You shouldn't need to define the %.o: %.cpp rule yourself, Make knows how to compile C++.
Indent with tabs, not spaces; Make is sensitive to the difference.
Every object file should depend on the headers included in the source files it depends on. You probably need Main.o : Main.cpp SelectionSort.h.
build shouldn't depend on clean, it defeats one of Make's main features (selectively recompilation when files have changed).
If you make build the first target, you can run Make without a target to get a full compile. It's customary to call the main target all.

minimum c++ make file for linux

I've looking to find a simple recommended "minimal" c++ makefile for linux which will use g++ to compile and link a single file and h file. Ideally the make file will not even have the physical file names in it and only have a .cpp to .o transform. What is the best way to generate such a makefile without diving into the horrors of autoconf?
The current dir contains, for example
t.cpp
t.h
and I want a makefile for that to be created. I tried autoconf but its assuming .h is gcc instead of g++. Yes, while not a beginner, I am relearning from years ago best approaches to project manipulation and hence am looking for automated ways to create and maintain makefiles for small projects.
If it is a single file, you can type
make t
And it will invoke
g++ t.cpp -o t
This doesn't even require a Makefile in the directory, although it will get confused if you have a t.cpp and a t.c and a t.java, etc etc.
Also a real Makefile:
SOURCES := t.cpp
# Objs are all the sources, with .cpp replaced by .o
OBJS := $(SOURCES:.cpp=.o)
all: t
# Compile the binary 't' by calling the compiler with cflags, lflags, and any libs (if defined) and the list of objects.
t: $(OBJS)
$(CC) $(CFLAGS) -o t $(OBJS) $(LFLAGS) $(LIBS)
# Get a .o from a .cpp by calling compiler with cflags and includes (if defined)
.cpp.o:
$(CC) $(CFLAGS) $(INCLUDES) -c $<
Here is a generic makefile from my code snippets directory:
SOURCES=$(wildcard *.cpp)
OBJECTS=$(SOURCES:.cpp=.o)
DEPS=$(SOURCES:.cpp=.d)
BINS=$(SOURCES:.cpp=)
CFLAGS+=-MMD
CXXFLAGS+=-MMD
all: $(BINS)
.PHONY: clean
clean:
$(RM) $(OBJECTS) $(DEPS) $(BINS)
-include $(DEPS)
As long as you have one .cpp source producing one binary, you don't need anything more. I have only used it with GNU make, and the dependency generation uses gcc syntax (also supported by icc). If you are using the SUN compilers, you need to change "-MMD" to "-xMMD". Also, ensure that the tab on the start of the line after clean: does not get changed to spaces when you paste this code or make will give you a missing separator error.
Have you looked at SCons?
Simply create a SConstruct file with the following:
Program("t.cpp")
Then type:
scons
Done!
Assuming no preconfigured system-wide make settings:
CXX = g++
CPPFLAGS = # put pre-processor settings (-I, -D, etc) here
CXXFLAGS = -Wall # put compiler settings here
LDFLAGS = # put linker settings here
test: test.o
$(CXX) -o $# $(CXXFLAGS) $(LDFLAGS) test.o
.cpp.o:
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $<
test.cpp: test.h
a fairly small GNU Makefile, using predefined rules and auto-deps:
CC=c++
CXXFLAGS=-g -Wall -Wextra -MMD
LDLIBS=-lm
program: program.o sub.o
clean:
$(RM) *.o *.d program
-include $(wildcard *.d)
Have you looked at OMake ?
OMakeroot
open build/C
DefineCommandVars()
.SUBDIRS: .
OMakefile
.DEFAULT: $(CXXProgram test, test)
Then on Linux or Windows, simply type:
omake
As a bonus, you automatically get:
parallel builds with the -j option (same as make).
MD5 checksums instead of timestamps (build becomes resilient to time synchronization failures).
Automatic and accurate C/C++ header dependencies.
Accurate inter-directory dependencies (something that recursive make does not offer).
Portability (1 build chain to rule them all, immune to path style issues).
A real programming language (better than GNU make).
Some good references on creating a basic Makefile
http://en.wikipedia.org/wiki/Make_(software)
http://mrbook.org/tutorials/make/
http://www.opussoftware.com/tutorial/TutMakefile.htm
http://www.hsrl.rutgers.edu/ug/make_help.html
The first couple in particular have minimal example Makefiles like you were describing. Hope that helps.
SConstruct with debug option:
env = Environment()
if ARGUMENTS.get('debug', 0):
env.Append(CCFLAGS = ' -g')
env.Program( source = "template.cpp" )
florin has a good starting point. I didn't like gnu autoconf so I started there and took the concept further and called it the MagicMakefile. I have 3 versions of it from simple to more complex. The latest is now on github: https://github.com/jdkoftinoff/magicmake
Basically, it assumes you have a standard layout for the source files of your project and uses the wildcard function to create the makefile rules on the fly which are then eval'd, handling header file dependancies, cross compiling, unit tests, install, and packaging.
[edit] At this point I use cmake for all my projects since it generates useful project files for many build systems.
jeff koftinoff
I was hunting around for what a minimal Makefile might look like other than
some_stuff:
#echo "Hello World"
I know I am late for this party, but I thought I would toss my hat into the ring as well. The following is my one directory project Makefile I have used for years. With a little modification it scales to use multiple directories (e.g. src, obj, bin, header, test, etc). Assumes all headers and source files are in the current directory. And, have to give the project a name which is used for the output binary name.
NAME = my_project
FILES = $(shell basename -a $$(ls *.cpp) | sed 's/\.cpp//g')
SRC = $(patsubst %, %.cpp, $(FILES))
OBJ = $(patsubst %, %.o, $(FILES))
HDR = $(patsubst %, -include %.h, $(FILES))
CXX = g++ -Wall
%.o : %.cpp
$(CXX) $(HDR) -c -o $# $<
build: $(OBJ)
$(CXX) -o $(NAME) $(OBJ)
clean:
rm -vf $(NAME) $(OBJ)
If your issues are because autoconf thinks the .h file is a c file, try renaming it to .hpp or .h++