C++ makefile multiple headers one cpp - c++

I am having compiling errors. I have one cpp file and many headers. For the makefile I thought I needed to list all the headers file. The LinkedBinaryTree.h contains includes for all the other header files. This what I wrote:
all: hw4a
hw4a: LinkedBinaryTree.cpp linkedBinaryTree.h booster.h arrayQueue. binaryTree.h binaryTreeNode.h myExceptions.h queue.h
g++ -o hw4a LinkedBinaryTree.cpp LinkedBinaryTree.h booster.h arrayQueue.h binaryTree.h binaryTreeNode.h myExceptions.h queue.h
clean:
rm hw4a
I was told that O just needed to do:
g++ LinkedBinaryTree.cpp -o bst.exe
Which one is correct?

The latter is correct: g++ -o result.exe source.cpp. You must not include header files in the compiler command, since they are automatically included by the preprocessor already.
Of course the header files are still dependencies and must be listed in the makefile. That's why there is a special universal syntax to refer to the first reference only:
.phony: all clean
all: result.exe
result.exe: main.o
$(CXX) -o $# $+
main.o: main.cpp class1.hpp lib2.hpp
$(CXX) -c -o $# $<
The $+ means "all dependecies" (with repetition; $^ also expands to all dependencies but uniquified), as you need for linking, while $< only means "first dependency", as you need for compiling.
While you're at it, sprinkle generous warning flags over your compiler commands.

What you were told. Includes should be included, not being compiled as separate units.

Related

makefile: how to specify header files

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

Makefile | Dependency on another Header file included in Header file

Suppose I have below rule in Makefile.
test.o: test.cpp foo.h
g++ -c -o test.o test.cpp
Now suppose foo.h includes bar.h as seen below.
user $ head -n 5 foo.h
#include"bar.h"
/*
.
.
*/
user $
Will the test.o be built again if there are any changes in bar.h ?
Or should I specifically mention bar.h in the rule as below:
test.o: test.cpp foo.h bar.h
g++ -c -o test.o test.cpp
Will the test.o be built again if there are any changes in bar.h?
No. Make has no way of knowing about this dependency, or checking for changes in your #includes.
Except, of course, if you leave handling header dependencies to the entity who knows about them: The compiler. (Assuming GCC and GNU make in this example.)
Don't list headers as dependencies at all.
Generate a list of source files in your project.
SRCFILES := ...
Generate a list of dependency files, one .d file for each SRCFILE.
DEPFILES := $(patsubst %.cpp,%.d,$(SRCFILES))
Include those dependency files into your Makefile. (The leading - means Make will not generate an error if they don't exist, e.g. on first compilation.)
-include $(DEPFILES)
Using a generic rule, let the compiler generate a list of the header dependencies during compilation of each source file.
%.o: %.cpp Makefile
#$(CXX) $(CXXFLAGS) -MMD -MP -c $< -o $#
-MMD generates Make rules making the object files depend on any (non-system) header files included, named *.d. -MP adds dummy rules that avoid errors should a header file be removed from your sources.
GCC (and probably Clang) can build a list of dependencies for you; This way, you can simply make your object files from their source (cpp) file:
depend: .depend
.depend: $(SRC_FILES)
rm -f ./.depend
$(CC) $(CFLAGS) -MM $^ -MF ./.depend;
include .depend
%.o: %.cpp
$(CC) $(CFLAGS) -c $<
You might also find interest in the makedepend tool.

Understanding a makefile better - How the .o file gets generated in this case

I currently have the following makefile (I am using an example of an online tutorial) which works however I have a few questions regarding this:
# *****************************************************
# Variables to control Makefile operation
CXX = g++
CXXFLAGS = -Wall -g
test: main.o car.o student.o house.o
$(CXX) $(CXXFLAGS) -o test main.o car.o student.o house.o
objcopy --only-keep-debug test test.debug
main.o: student.h house.h main.cpp
$(CXX) $(CXXFLAGS) -c main.cpp
car.o: car.h
student.o: student.h car.h
house.o: house.h
clean:
rm -rf *.o test *.debug
Here is my understanding of what is going on here please correct me if I am wrong. When initially test target is called it looks for the first dependency main.o This could either be a file or a target. Since there is no file called main.o it will look for main.o as a target. Once main.o as a target is found it looks for dependencies student.h house.h main.cpp since these exist as a file make then executes the recipe (command) which is $(CXX) $(CXXFLAGS) -c main.cpp. Now here is the part that I dont understand. When the second dependency car.o turn comes up make looks for car.h and finds it but there is no command that tells it to generate the .o file. How is the .o file being generated here ?
make contains several implicit rules. That means that make has built-in knowledge about how to create a .o file from a .cpp file without you telling it explicitly how to do that.
From the documentation:
Compiling C++ programs
n.o is made automatically from n.cc, n.cpp, or
n.C with a recipe of the form ‘$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c’. We
encourage you to use the suffix ‘.cc’ for C++ source files instead of
‘.C’
You may think of this as make having a built-in rule that looks quite like:
%.o : %.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $#
Read more about these implicit rules here and here.
There is a built in rule for generating an .o file from a .cpp file.
You have told it that is has an extra dependency of car.h, but not how to make car.o so it falls back on the built in rule, with car.h as an added dependency.
You could change
main.o: student.h house.h main.cpp
$(CXX) $(CXXFLAGS) -c main.cpp
to
main.o: student.h house.h
and it would build it too using the built in rule. Its documented here.
You could also use a built in rule to make your test binary, were you not also running the objcopy command.
Instead of
test: main.o car.o student.o house.o
$(CXX) $(CXXFLAGS) -o test main.o car.o student.o house.o
You could just use
test: main.o car.o student.o house.o
Most make (and similar) programs pre-define implicit rules for things like converting a source file (with any of a number of common extensions) to object file (using their default extension).
Typically that'll be equivalent to something like this:
.c.o:
$(CC) $(CFLAGS) -o $*.o -c $*.c
.cc.o:
$(CXX) $(CXXFLAGS) -o $*.o -c $*.cc
...with more for other common extensions, so it'll not only know how to compile most typical extensions (.c, .cc, .cpp, .C, etc.) to .o files, but also implicitly pick up the content of some variable you can specify as the set of flags to pass to the compiler when it does so.
As for the details of these rules: a rule like .cc.o: is an implicit rule--it basically says "if you have a .cc file you can create a .o file from it using this rule". These get used as kind of a backstop--if you have an explicit rule telling how to create some specific .o file, make will use that by preference--but if there isn't an explicit rule, it can fall back on the implicit rule instead.
The $* is a built-in macro, that expands to the base name (without the extension) of the source file. There are a number of them for just the base name of the source ($*) and the full name of the source file ($<). There are a number of other automatic variables like this, but from what I've seen most people using them rarely enough that they have to look them up when they need to use them.

My C++ makefile can not create object file for each .cpp code

My makefile compiles our C++ code without any problems but it can not create object files.
How do I need to modify this file in order to create the object file for each .cpp file?
Is there any problem if I proceed without creating an object file for each .cpp file ?
My makefile looks like this:
engine:main.cpp correlation.cpp correlation.h matcher.cpp matcher.h scheduler.cpp scheduler.h parser.cpp parser.h cache_manager.cpp cache_manager.h init.cpp init.h db_manager.cpp db_manager.h
g++ -o engine main.cpp correlation.cpp correlation.h matcher.cpp matcher.h scheduler.cpp scheduler.h parser.cpp parser.h cache_manager.cpp cache_manager.h init.cpp init.h db_manager.cpp db_manager.h -lpthread -lboost_regex -I/usr/include -ggdb \
-I/usr/include/oracle/11.1/client \
-L$(ORACLE_HOME)/lib -lclntsh -locci
clean:
rm -f engine
There's no problem if you skip naming object files. They'll still be created behind the scenes though.
The advantage of specifically creating object files is that you'll save time recompiling, since make will be able to skip any object file it doesn't have to recreate (since it's up-to-date; something that won't work with temporary files as they're deleted).
The easiest way to get this working is by using a special placeholder syntax in your makefile:
%.o: %.cpp
g++ -c -o $# $< $(YOUR_OTHER_PARAMS)
In this example you define a generic recipe for any file ending in .o to requiring a file with the same name ending in .cpp. $# is a special macro that will expand to the current output file, while $< will include the current input file.
In a similar way you may define macros for other files as well:
%.png: %.bmp
myinmageconverter -png $< $#
You can still name specific recipes, e.g. for cases where one specific file needs additional or different parameters. Just name it in your makefile as usual. The placeholder syntax will only try to match otherwise unmatched targets.
If you'd like to mention some generic or precompiled header, you can still include it (just like any other dependency):
%.o: %.cpp common.hpp
g++ -c -o $# $< $(YOUR_OTHER_PARAMS)
For the actual executable, you can then just define your components as usual, i.e. your example could look like this:
engine: main.o correlation.o matcher.o scheduler.o ...
g++ -o engine main.o correlation. matcher.o ...
%.o: %.cpp
g++ -c -o $# $< -lpthread -lboost_regex -I/usr/include -ggdb ...

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.