Makefile with subdirectories does not find headers - c++

I have the following directory structure (on Ubuntu):
MyProject/
Here is my Makefile
MyProject/src/headers
Here are more subfolders and .hpp files
MyProject/src/sources
Here are two .cpp files (main.cpp and another.cpp)
So I have used this tutorial to write my makefile, that looks like this:
cppsrc = $(wildcard src/sources/*.cpp)
obj = $(cppsrc:.cpp=.o)
flags = -I/usr/include/boost_1_72_0/ -pthread
cross: $(obj)
i686-atom-linux-gnu-g++ -o $# $^ $(flags)
It detects the .cpp file in the subdirectory (yay!).
But it does not detect the header files included in the .cpp file. So I have included the header in another.cpp like this:
#include "src/headers/another.hpp"
The command make cross gives me this error message:
g++ -c -o src/sources/another.o src/sources/another.cpp
src/sources/another.cpp:6:10: fatal error: src/headers/another.hpp: No such file or directory
#include "src/headers/another.hpp"
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
<builtin>: recipe for target 'src/sources/another.o' failed
make: *** [src/sources/another.o] Error 1
The error message makes me believe that makeapp looks for the header file in a position like this:
MyProject/src/sources/src/headers/
Is my assumption correct? What can I do to solve this?
Hope that someone will be able to help me. Thank you in advance.

You forgot to tell your compiler to look in the local directory (-I.), but there is a more serious problem: you are compiling your files with the HOST compiler and linking them together with a CROSS compiler. This will result in errors.
To fix it, you need to set variables used in the default COMPILE.cc rule, defined as follows:
COMPILE.cpp = $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
%.o: %.cpp
# commands to execute (built-in):
$(COMPILE.cpp) $(OUTPUT_OPTION) $<
So in your case:
CXX = i686-atom-linux-gnu-g++
CXXFLAGS += -I. -I/usr/include/boost_1_72_0/
LDFLAGS += -lpthread
cppsrc = $(wildcard src/sources/*.cpp)
obj = $(cppsrc:.cpp=.o)
cross: $(obj)
$(CXX) -o $# $^ $(LDFLAGS)

Related

Makefile by ocaml and cpp extension

I have large number of .ml and .cpp files in a same directory which are totally independent of each other. Is there any way I can compile them with Makefile without using external bash / shell scripts?
CC=g++
CFLAGS=-Wall -std=c++14 -Wno-unused-variable
CCML=ocamlc
SHELL := '/bin/bash'
.SUFFIXES = .cpp .ml
cpp_objs:=$(wildcard *.cpp)
ml_objs:=$(wildcard *.ml)
cpp_targets:=$(cpp_objs:.cpp= )
ml_targets:=$(ml_objs:.ml= )
targets:=$(cpp_targets) $(ml_targets)
.PHONY:all
all: $(targets)
# all: $(cpp_targets)
.ml:
$(CCML) -o $# $<
.cpp:
$(CC) $(CFLAGS) -o $# $<
What's wrong with this Makefile that only recognises my .cpp files :
make: *** No rule to make target `[ML-FILES]', needed by `all'. Stop.
Update: All the *.ml and *.cpp files has unique name in the directory.
Thanks.
According to the manual you are supposed to configure .SUFFIXES like a target, not like a variable:
.SUFFIXES: .cpp .ml
However, the better approach is to use pattern rules so you can drop the use of .SUFFIXES entirely.
%: %.ml
$(CCML) -o $# $<

Why does code can not be build when source location is changed in Makefile?

I have a problem with building cpp files when I move them out of Makefile folder. Anyone knows why?
Snippet from the makefile:
CC = qcc -Vgcc_nto$(PLATFORM)
CXX = qcc -lang-c++ -Vgcc_nto$(PLATFORM)
LD = $(CXX)
DEPS = -Wp,-MMD,$(#:%.o=%.d),-MT,$#
CFLAGS=-Wall -g -ggdb -O0
DIR_SRC =./
DIR_OBJ =./
SRCS := $(wildcard $(DIR_SRC)/*.cpp)
OBJECTS := $(SRCS:$(DIR_SRC)/%.cpp=$(DIR_OBJ)/%.o)
all: hello_world_test
$(DIR_OBJ)/%.o : $(DIR_SRC)/%.c
$(CXX) $(CFLAGS) ${CPPFLAGS} ${DEPS} -c $< -o $#
hello_world_test: hello_world_test.o
$(CXX) hello_world_test.o $(LDFLAGS) $(LIBPATH) $(LDLIBS) -o $#
So in this way, everything is fine but when I move sources to one folder back called "test"
DIR_SRC =../test
it doesnt work anymore with the message:
make: *** No rule to make target 'hello_world_test.o', needed by 'hello_world_test'. Stop.
Because:
hello_world_test: hello_world_test.o
your hello_world_test depends on hello_world_test.o. But your rule tells make how to build $(DIR_OBJ)/%.o and hello_world_test.o doesn't match that pattern. Pattern matching in targets is simple string matching, it doesn't do pathname simplification. You should write your prerequisite as:
hello_world_test: $(DIR_OBJ)/hello_world_test.o
Note that you have two slashes here: one in DIR_OBJ and one after it. But anyway.
The reason it worked before is that make was using its built-in recipe to build object files, not your recipe; the built-in recipe has the pattern:
%.o : %.c
which matched your object file. If you run make with the -r option to remove all built-in rules, you would have seen a failure there as well.
Thank you for your answer. I found out that the problem was in the rule, like you said.
I changed to $(DIR_OBJ)/%.o : $(DIR_SRC)/%.cpp (before it was .c instead of .cpp :) ) and it works now with changing the DIR_SRC.
I didn't observe this since I was able to build from the current directory but realized after your answer about built-in rule.
Another questions:
1) Does this rule:
$(DIR_OBJ)/%.o : $(DIR_SRC)/%.cpp
$(CXX) $(CFLAGS) ${CPPFLAGS} ${DEPS} -c $< -o $#
says next: do compile all .cpp files and make .o files out of it and put the .o files in DIR_OBJ?
2) Why I cant change DIR_OBJ location to for instance:
DIR_OBJ =../test and then use hello_world_test: $(DIR_OBJ)/hello_world_test.o to build the executable?
When I do it I get an error: cannot find hello_world_test.o: No such file or directory.
I see that .o and .d files are created in the directory where DIR_OBJ is defined (either in ./ or in ../test) and then it makes me quite confused why hello_world_test cant fine prerequisite $(DIR_OBJ)/hello_world_test.o but it only looks in the current folder where the Makefile is.
I realized what was the problem:
I haven't added $(DIR_OBJ)/hello_world_test.o in
$(CXX) hello_world_test.o $(LDFLAGS) $(LIBPATH) $(LDLIBS) -o $#
but now still confused, if my understanding is right that $(DIR_OBJ)/%.o : $(DIR_SRC)/%.cpp will create $(DIR_OBJ)/hello_world_test.o how come that hello_world_client: $(DIR_OBJ)/hello_world_client.o couldn't find prerequisite?

makefile generate file object for the header file only?

im having probleme in makefile.
when i execute make commande in the terminal it has to generate header.o and main.o and then combine them to generate the excutable kmeans.o file,but it did not, it only generate header.o which is km.o and stop without any error message.
this is my make file :
CFLAGS = -ggdb
DEFINES = -DDEBUGGA
INCLUDES =
LIBS = -lstdc++
EXAMPLE = kmeans.o
CC=g++
.cpp.o:
$(CC) -c $(CFLAGS) $(DEFINES) $(INCLUDES) $<
all:: km.o kmeans.o
km.o: km.cpp km.hpp
gnuplot_i.o: gnuplot_i.hpp
kmeans.o: main.cpp
kmeans: $(EXAMPLE)
$(CC) -o $# $(CFLAGS) $(EXAMPLE) $(LIBS)
clean:
rm -f $(EXAMPLE) kmeans
The km.cpp and km.hpp is the header file and it implementation.
gnuplot_i.hpp is header with its implementation.
main.cpp file the file which links all these libries.
The default target in this makefile is all: km.o kmeans.o.
So when you run make that is what will run. So make will create those two .o files and stop.
If you want make to be the same as make kmeans then you need all: kmeans as your default rule or to move the kmeans target above the all target (since the first target is the default one).

Makefile: How to correctly include header file and its directory?

I have the following makefile:
CC=g++
INC_DIR = ../StdCUtil
CFLAGS=-c -Wall -I$(INC_DIR)
DEPS = split.h
all: Lock.o DBC.o Trace.o
%.o: %.cpp $(DEPS)
$(CC) -o $# $< $(CFLAGS)
clean:
rm -rf *o all
This makefile and all three source files Lock.cpp, DBC.cpp, Trace.cpp are located in the current directory called Core. One of the source file Trace.cpp contains a line that includes a header file outside the current directory:
//in Trace.cpp
#include "StdCUtil/split.h"
The header file split.h is located at one level above the current directory and then in the subdirectory called StdCUtil. So that's why I added INC_DIR = ../StdCUtil in the makefile. The overall directory structure looks like the following:
root
|___Core
| |
| |____Makefile
| |____DBC.cpp
| |____Lock.cpp
| |____Trace.cpp
|
|___StdCUtil
|___split.h
But when I make it, it gives me the error:
Trace.cpp:8:28: fatal error: StdCUtil/split.h: No such file or directory
#include "StdCUtil/split.h"
^
compilation terminated.
<builtin>: recipe for target 'Trace.o' failed
Why this doesn't find the header file split.h even if I specify the INC_DIR in the makefile? How to correct this?
These lines in your makefile,
INC_DIR = ../StdCUtil
CFLAGS=-c -Wall -I$(INC_DIR)
DEPS = split.h
and this line in your .cpp file,
#include "StdCUtil/split.h"
are in conflict.
With your makefile in your source directory and with that -I option you should be using #include "split.h" in your source file, and your dependency should be ../StdCUtil/split.h.
Another option:
INC_DIR = ../StdCUtil
CFLAGS=-c -Wall -I$(INC_DIR)/.. # Ugly!
DEPS = $(INC_DIR)/split.h
With this your #include directive would remain as #include "StdCUtil/split.h".
Yet another option is to place your makefile in the parent directory:
root
|____Makefile
|
|___Core
| |____DBC.cpp
| |____Lock.cpp
| |____Trace.cpp
|
|___StdCUtil
|___split.h
With this layout it is common to put the object files (and possibly the executable) in a subdirectory that is parallel to your Core and StdCUtil directories. Object, for example. With this, your makefile becomes:
INC_DIR = StdCUtil
SRC_DIR = Core
OBJ_DIR = Object
CFLAGS = -c -Wall -I.
SRCS = $(SRC_DIR)/Lock.cpp $(SRC_DIR)/DBC.cpp $(SRC_DIR)/Trace.cpp
OBJS = $(OBJ_DIR)/Lock.o $(OBJ_DIR)/DBC.o $(OBJ_DIR)/Trace.o
# Note: The above will soon get unwieldy.
# The wildcard and patsubt commands will come to your rescue.
DEPS = $(INC_DIR)/split.h
# Note: The above will soon get unwieldy.
# You will soon want to use an automatic dependency generator.
all: $(OBJS)
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
$(CC) $(CFLAGS) -c $< -o $#
$(OBJ_DIR)/Trace.o: $(DEPS)
The preprocessor is looking for StdCUtil/split.h in
./ (i.e. /root/Core/, the directory that contains the #include statement). So ./ + StdCUtil/split.h = ./StdCUtil/split.h and the file is missing
and in
$INC_DIR (i.e. ../StdCUtil/ = /root/Core/../StdCUtil/ = /root/StdCUtil/). So ../StdCUtil/ + StdCUtil/split.h = ../StdCUtil/StdCUtil/split.h and the file is missing
You can fix the error changing the $INC_DIR variable (best solution):
$INC_DIR = ../
or the include directive:
#include "split.h"
but in this way you lost the "path syntax" that makes it very clear what namespace or module the header file belongs to.
Reference:
C++ #include semantics
EDIT/UPDATE
It should also be
CXX = g++
CXXFLAGS = -c -Wall -I$(INC_DIR)
...
%.o: %.cpp $(DEPS)
$(CXX) -o $# $< $(CXXFLAGS)
This is not a question about make, it is a question about the semantic of the #include directive.
The problem is, that there is no file at the path "../StdCUtil/StdCUtil/split.h". This is the path that results when the compiler combines the include path "../StdCUtil" with the relative path from the #include directive "StdCUtil/split.h".
To fix this, just use -I.. instead of -I../StdCUtil.
Try INC_DIR=../ ../StdCUtil.
Then, set CCFLAGS=-c -Wall $(addprefix -I,$(INC_DIR))
EDIT: Also, modify your #include to be #include <StdCUtil/split.h> so that the compiler knows to use -I rather than local path of the .cpp using the #include.

C++ Makefile %.c works, %.cpp not?

i wrting a simple makefile for c++ files but here is a problem i do not understand.
I have 2 folders
/src for .cpp files
main.cpp
check cpp
/include for .hpp files
check.hpp
My Makefiles looks like this
LIBS = -lsfml-graphics -lsfml-window -lsfml-system
CC = g++
VPATH = src include
CPPFLAGS = -I include
### Files ###
OBJ = main.o check.o
### Rules ###
all: sfml-app
sfml-app: $(OBJ)
$(CC) -o sfml-app $(OBJ) $(LIBS)
%.o: %.c
$(CC) -c $<
clean:
rm -rf *o $(OBJ)
if i use my makefile likes this, everything works fine.
But if i change %.o: %.c to %.o: %.cpp he said
src/main.cpp:2:21: critical error: check.hpp: file or folder not found
is it wrong to write .cpp instead of .c even it is a c++ project? This confused me a bit. Why .c works finde and .cpp not.
thanks for your help :) !
Because make is trying to build a .o from a .cpp file, when you write a rule like %.o : %.c it has no effect on make because make is not trying to build a .o from a .c. Because of that, make is using its own built-in rules to compile the .cpp file into the .o file and the built-in rule works fine.
When you change the rule to be %.o : %.cpp, now your rule matches what make wants to build and so make uses your rule instead of its own built-in rule. Obviously your rule is broken and does not work.
Why does it not work? Because you are not using $(CPPFLAGS), and so the -I include flags are not passed to the compiler, and so the compiler cannot find your header files.
The flags variable for the C++ language is called CXXFLAGS, and you should be using $(CXX) instead of $(CC) in your code. CPPFLAGS is the variable for preprocessor arguments.
Use standard make file flags
CXX for g++
CPP for cpp files
and try:
%.o: %.cpp
$(CXX) $(CXXFLAGS) -c $<
The default rules are:
For C files:
$(CC) -c $(CPPFLAGS) $(CFLAGS) $?
For C++ files
$(CXX) -c $(CPPFLAGS) $(CXXFLAGS) $?
For linking:
$(CC) $(LDFLAGS) $^ $(LOADLIBES)
CPPFLAGS is supposed to be pre-processor flags. The other two (CFLAGS CXXFLAGS) are flags for the specific languages. You should adjust your usage as such.
Also it is unusual to exlicitly define the object files:
OBJ = main.o check.o
It is more usual to define the source files. Then define object files in terms of the source files
OBJ = $(patsubst %.cpp, %.o, $(SRC))
Personally I like to build everything in the directory so use
SRC = $(wildcard *.cpp)
But this will depend a lot on the project.