Modify the makefile to include subdirectories - c++

I'm working with a small program in c++ to learn the makefile.
The program has 2 source files (main.cpp and classf.cpp) and one header file (classf.h). All files are included in the project directory which is called "testmake". This is the generated makefile by eclipse on windlows:
CXXFLAGS = -O2 -g -Wall -fmessage-length=0
OBJS = main.o classf.o
LIBS =
TARGET = createPddl.exe
$(TARGET): $(OBJS)
$(CXX) -o $(TARGET) $(OBJS) $(LIBS)
all: $(TARGET)
clean:
rm -f $(OBJS) $(TARGET)
I would like to modify the makefile to accept new sub-directories, e.g, when I add a folder called "testmake/src" and move the file main.cpp inside it, folder called "testmake/csource" and move the classf.cpp inside it, and create a folder called "testmake/cheader" and move the classf.h inside it.

This makefile was genereated automatically by eclipse, and does not accept any changes. There for i have created manually a make file which is working with any c++ project that has a structure as tree.
I actually use this Makefile in general
CC := g++ # This is the main compiler
SRCDIR := src
BUILDDIR := build
TARGETDIR :=bin/
TARGET := pddlcrate
DATADIR := data
SRCEXT := cpp
SOURCES := $(shell find $(SRCDIR) -type f -name *.$(SRCEXT))
OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.o))
CFLAGS := -g # -Wall
#LIB := -pthread -lmongoclient -L lib -lboost_thread-mt -lboost_filesystem-
mt -lboost_system-mt
INC := -I include
$(TARGET): $(OBJECTS)
#echo " Linking..."
#echo " $(CC) $^ -o $(TARGETDIR)$(TARGET) $(LIB)"; $(CC) $^ -o
$(TARGETDIR)$(TARGET) $(LIB)
$(BUILDDIR)/%.o: $(SRCDIR)/%.$(SRCEXT)
#mkdir -p $(BUILDDIR)
#echo " $(CC) $(CFLAGS) $(INC) -c -o $# $<"; $(CC) $(CFLAGS) $(INC) -c - o $# $<
clean:
#echo " Cleaning...";
#echo " $(RM) -r $(BUILDDIR) $(TARGET)"; $(RM) -r $(BUILDDIR) $(TARGET)
for any c++ project with this tree structure
$ tree .
├── Makefile
├── bin
>exefile
├── include
> *.h files
├── obj
> *.o files
├── src
>*.cpp

Related

Preprocessor macro definition via a Makefile does not work properly in c++

For my c++ code I need a custom processor macro that will be defined during compilation. According to what I have read I concluded in the following Makefile:
CC := g++
# Folders
SRCDIR := src
BUILDDIR := build
TARGETDIR := bin
# Targets
EXECUTABLE := app
TARGET := $(TARGETDIR)/$(EXECUTABLE)
SRCEXT := cpp
SOURCES := $(shell find $(SRCDIR) -type f -name *.$(SRCEXT))
OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.o))
CFLAGS := -Dcustom_macro -g -c -Wall -std=c++14
INC := -I include
$(TARGET): $(OBJECTS)
#echo " Linking..."
$(CC) $^ -o $(TARGET) $(LIB)
$(BUILDDIR)/%.o: $(SRCDIR)/%.$(SRCEXT)
#mkdir -p $(BUILDDIR)
$(CC) $(CFLAGS) $(INC) -c -o $# $<
clean:
#echo " Cleaning...";
$(RM) -r $(BUILDDIR) $(TARGET)
The build is successful but when I run my app the code inside #ifdef custom_macro #endif is not executed but only when I change it to #ifndef .
I also tried to set -Dcustom_macro=1 but I had the same behavior.
I also tried to insert this with the CPPFLAGS macro as following :
CC := g++
# Folders
SRCDIR := src
BUILDDIR := build
TARGETDIR := bin
# Targets
EXECUTABLE := app
TARGET := $(TARGETDIR)/$(EXECUTABLE)
SRCEXT := cpp
SOURCES := $(shell find $(SRCDIR) -type f -name *.$(SRCEXT))
OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.o))
CFLAGS := -g -c -Wall -std=c++14
CPPFLAGS := -Dcustom_macro
INC := -I include
$(TARGET): $(OBJECTS)
#echo " Linking..."
$(CC) $^ -o $(TARGET) $(LIB)
$(BUILDDIR)/%.o: $(SRCDIR)/%.$(SRCEXT)
#mkdir -p $(BUILDDIR)
$(CC) $(CPPFLAGS) $(CFLAGS) $(INC) -c -o $# $<
clean:
#echo " Cleaning...";
$(RM) -r $(BUILDDIR) $(TARGET)
But nothing changed. The parameters that are passed to make according to compiler are:
The parameteres that are passed to make are the following:
g++ -Dcustom_macro -g -c -Wall -std=c++14 -I include -c -o build/main.o src/main.cpp
Does anyone has any idea what I'm doing wrong?
Seems like you missed a space before macro name
CPPFLAGS := -D custom_macro

Makefile: compile objects to different directory and build from there

My Makefile:
CXX = clang++
CXXFLAGS = -g -Wall -std=c++14
LDFLAGS = -lboost_system -lcrypto -lssl -lcpprest -lpthread
OBJDIR = obj
SRCDIR = .
SRC := $(shell find $(SRCDIR) -name "*.cpp")
OBJ := $(SRC:%.cpp=%.o)
APP = run
all: $(APP)
$(APP): $(OBJ)
#echo "== LINKING EXECUTABLE $(APP)"
#$(CXX) $^ $(LDFLAGS) -o $(APP)
%.o: %.cpp
#echo "COMPILING SOURCE $< INTO OBJECT $#"
#$(CXX) -c $(CXXFLAGS) $< -o $#
clean:
find . -name *.o -delete
rm -f $(APP)
Directory structure:
Makefile
sources/
directory1
...cpp
directory2
...cpp
...
main.cpp
obj/
I try to make make create *.o files in a directory obj/ and then compile the final executable from there. I tried various approaches and they fail because of the project structure that stores *.cpp files in sub-directories. Particularly, I've tried the following: https://stackoverflow.com/a/26032630/2042546
I've also tried to manipulate the command itself clang++ $< -o obj/$# but it breaks whole idea of make and it's dependency management.
If I modify OBJ via patsubstr and notdir, make becomes unable to deduce dependency of a *.o on a corresponding *.cpp by it's path, cause *.o's path loses it's directory part and becomes unable to find it's *.cpp file when executing %.o:%.cpp rule (I hope I managed to write down my thoughts correctly).
If you want objects to live in the same source directory structure but under obj, then simply change your pattern rule (and how you generate the object files). And you should create the directory first:
OBJ := $(SRC:%.cpp=$(OBJDIR)/%.o)
...
$(OBJDIR)/%.o: %.cpp
#echo "COMPILING SOURCE $< INTO OBJECT $#"
#mkdir -p '$(#D)'
#$(CXX) -c $(CXXFLAGS) $< -o $#

Recursive makefile for c++ source

I've been struggling with makefiles for a while now, since I don't really get how they work...
My directory structure is as followed:
--bin/
--build/
--includes/
--src/
----classes/
------somefiles.hpp
------somefiles.cpp
----states/
------somestates.hpp
----main.cpp
----few-other-files.cpp
--Makefile
--.gitignore
Which worked fine with my makefile, until I started adding those subdirs, classes and states
I can't seem to find how to include those subdirs in my makefile which is:
CC := g++
SRCDIR := src
BUILDDIR := build
TARGET := bin/game
SRCEXT := cpp
SOURCES := $(shell find $(SRCDIR) -type f -name *.$(SRCEXT))
OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.o))
CFLAGS := -g -Wall
LIB := -lsfml-audio -lsfml-graphics -lsfml-network -lsfml-system -lsfml-window
INC := -I includes -I /usr/local/include -L /usr/local/lib
$(TARGET): $(OBJECTS)
#echo "Linking..."
#echo "$(CC) $^ -o $(TARGET) $(LIB)"; $(CC) $^ -o $(TARGET) $(LIB)
$(BUILDDIR)/%.o: $(SRCDIR)/%.$(SRCEXT)
#mkdir -p $(BUILDDIR)
#echo "$(CC) $(CFLAGS) $(INC) -c -o $# $<"; $(CC) $(CFLAGS) $(INC) -c -o $# $<
clean:
#echo "Cleaning..."
#echo "$(RM) -r $(BUILDDIR) $(TARGET)"; $(RM) -r $(BUILDDIR) $(TARGET)
.PHONY: clean
Problem: Fatal error: can't create build/classes/stateManager.o: No such file or directory
Normally, the problem is that it can't build the directory. But I thought the mkdir -p would solve that.
Any help is greatly appreciated.
Replace:
mkdir -p $(BUILDDIR)
with
mkdir -p $(#:D)
Another way is to let make treat directories as targets and have them automatically created for you, so that you do not have to clutter your recipes with mkdir -p invocations:
.SECONDEXPANSION:
# Make the object file depend on its directory using order-only dependency.
$(BUILDDIR)/%.o: $(SRCDIR)/%.$(SRCEXT) | $$(dir $$#)
$(CC) $(CFLAGS) $(INC) -c -o $# $<
# Let make create the directories for your targets.
%/:
mkdir -p $#
# Do not remove the directories because they are "intermediate" targets.
.PRECIOUS : %/

How to add cap_net_raw capability via a Makefile to c++ executable file on linux

I have created a c++ that runs on Linux and on of its functionalities is to ping on a provided host. The ping has been based on relevant Poco libraries. However in order to run successfully on linux the produced c++ executable file should have the cap_net_raw capability set by giving
setcap cap_net_raw=ep /bin/C++_APP
I have also used the following Makefile based on an example I found by googling.
CC := g++
# Folders
SRCDIR := src
BUILDDIR := build
TARGETDIR := bin
# Targets
EXECUTABLE := C++_APP
TARGET := $(TARGETDIR)/$(EXECUTABLE)
SRCEXT := cpp
SOURCES := $(shell find $(SRCDIR) -type f -name *.$(SRCEXT))
OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.o))
CFLAGS := -c -Wall
INC := -I include -I /usr/local/include
LIB := -L /usr/local/lib -lPocoFoundation -lPocoNet -lPocoUtil
$(TARGET): $(OBJECTS)
#echo " Linking..."
#echo " $(CC) $^ -o $(TARGET) $(LIB)"; $(CC) $^ -o $(TARGET) $(LIB)
$(BUILDDIR)/%.o: $(SRCDIR)/%.$(SRCEXT)
#mkdir -p $(BUILDDIR)
#echo " $(CC) $(CFLAGS) $(INC) -c -o $# $<"; $(CC) $(CFLAGS) $(INC) -c -o $# $<
clean:
#echo " Cleaning...";
#echo " $(RM) -r $(BUILDDIR) $(TARGET)"; $(RM) -r $(BUILDDIR) $(TARGET)
.PHONY: clean
I added the following command as the last build command
#echo "Setting Capabilities"; sudo setcap cap_net_raw=ep $(TARGETDIR)/$(EXECUTABLE)
However I got the following error:
Failed to set capabilities on file `bin/NPT' (Invalid argument) The
value of the capability argument is not permitted for a file. Or the
file is not a regular (non-symlink) file
On the other hand when I give the command after the build of the c++ executable everything works fine. What am I doing wrong?
You added the command at the wrong place. You need to add it after the executable is made, not before. Try this:
$(TARGET): $(OBJECTS)
#echo " Linking..."
#echo " $(CC) $^ -o $(TARGET) $(LIB)"; $(CC) $^ -o $(TARGET) $(LIB)
#echo " Setting Capabilities"; sudo setcap cap_net_raw=ep $(TARGET)

How to compile/link a unittest in a Linux Makefile correctly?

On a Linux system I want to compile and link an unittest using the gtest framework. I am using the following Makefile:
CC := g++ # This is the main compiler
SRCDIR := src
BUILDDIR := build
TARGET := bin/myapp
TEST := tester
SRCEXT := cpp
SOURCES := $(shell find $(SRCDIR) -type f -name *.$(SRCEXT))
OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.o))
CFLAGS := -g
LIB := -pthread -L lib -L /usr/local/lib -lsqlite3 -lboost_thread -lcrypto
INC := -I include
$(TARGET): $(OBJECTS)
#echo " Linking..."
#echo " $(CC) $^ -g -o $(TARGET) $(LIB)"; $(CC) $^ -o $(TARGET) $(LIB)
$(BUILDDIR)/%.o: $(SRCDIR)/%.$(SRCEXT)
#mkdir -p $(BUILDDIR)
#echo " $(CC) $(CFLAGS) $(INC) -c -o $# $<"; $(CC) $(CFLAGS) $(INC) -c -o $# $<
clean:
#echo " Cleaning...";
#echo " $(RM) -r $(BUILDDIR) $(TARGET)"; $(RM) -r $(BUILDDIR) $(TARGET)
# Tests
$(TEST): $(OBJECTS)
#echo " Compiling test..."
$(CC) $(CFLAGS) test/tester.cpp $(INC) -c -o build/$(TEST).o
#echo " Linking test..."
$(CC) $(CFLAGS) $(INC) -pthread test/tester.cpp /usr/lib/libgtest.a $(LIB) -L build build/tester.o -o bin/$(TEST)
.PHONY: clean
The compilation of the main application (myapp) works just fine, but I get into trouble compiling/linking the test file located in the test directory.
When I do NOT include any other library (from src or include, respectively) then the following line
$(CC) $(CFLAGS) -pthread test/tester.cpp /usr/lib/libgtest.a $(INC) -o bin/$(TEST)
just works perfect and creates a runnable executable. However, when I try to include some library from my project in tester.cpp like e.g.
#include "MyClass.h"
(which is defined as MyClass.h in include and as MyClass.cpp in src) then, with the above Makefile, I get various undefined reference errors (in what I have labelled as the 'compile' stage for 'tester').
I am not sure if I should compile the file tester.cpp first and then link all the libraries, or if I should do everything in one step? I do not know how to do either.
Any advice on fixing this Makefile above is appreciated...
OBJECTS := $(patsubst $(SRCDIR)/%.$(SRCEXT),$(BUILDDIR)/%.o,$(SOURCES))
OBJECTS := $(filter-out $(BUILDDIR)/main.o, $(OBJECTS))
$(TARGET): $(OBJECTS) $(BUILDDIR)/main.o
#echo " Linking..."
$(CC) $^ -o $# $(LIB)
tester: bin/$(TEST)
bin/$(TEST): build/$(TEST).o $(OBJECTS)
#echo " Linking test..."
$(CC) $(INC) -pthread $^ /usr/lib/libgtest.a $(LIB) -L build -o $#
P.S. Please don't edit the question like that, after you have answers. If you want to make a change (that doesn't render the existing answers meaningless), add new test to the bottom of the question, preferably with "EDIT:".