build c++ project using Make from two source directories in Linux - c++

I have a c++ project in Linux in which source files are in 2 directories as shown below. Currently, the Makefile only compiles the files in the source/ directory, but not those in "/" directory. I've tried many hacks to no avail. How do you instruct Makefile to compile the source files in "/" directory after compiling those in source/, and put them in the obj/ directory ?
I've tried many things to no avail...
A savvy hand is welcome !!
/
Makefile
file1.cpp
file2.cpp ...
source/
file30.cpp file31.cpp ...
obj/
file30.o file31.o ...
CC = g++
CXXFLAGS = -std=c++11 -Wall
LDFLAGS = -pthread
APPNAME = trading_app
EXT = .cpp
SRCDIR = source
OBJDIR = obj
SRC = $(wildcard $(SRCDIR)/*$(EXT))
OBJ = $(SRC:$(SRCDIR)/%$(EXT)=$(OBJDIR)/%.o)
DEP = $(OBJ:$(OBJDIR)/%.o=%.d)
RM = rm
DELOBJ = $(OBJ)
all: $(APPNAME)
$(APPNAME): $(OBJ)
#echo "building the executable..."
$(CC) $(CXXFLAGS) -o $# $^ $(LDFLAGS)
%.d: $(SRCDIR)/%$(EXT)
#$(CPP) $(CFLAGS) $< -MM -MT $(#:%.d=$(OBJDIR)/%.o) >$#
$(OBJDIR)/%.o: $(SRCDIR)/%$(EXT)
$(info $$OBJ is [${OBJ}])
$(CC) $(CXXFLAGS) -o $# -c $<

Well, first you search only for files in the SRCDIR directory:
SRC = $(wildcard $(SRCDIR)/*$(EXT))
but not for files in the current directory. So of course make won't try to compile source files in the current directory. If you want to build files in the current directory you need to add them to SRC.
Then you write a rule telling make how to compile files in the SRCDIR subdirectory and put them into the OBJDIR subdirectory:
$(OBJDIR)/%.o: $(SRCDIR)/%$(EXT)
but you don't have a rule telling make how to compile files in the current directory and put them into the OBJDIR subdirectory. If you want make to know how to do that you have to give it a rule in the makefile that will do it.

Related

Makefile target with wildcard is not working

I have a simple project, whose folder structure is something like:
ls -R
.:
build include makefile src
./build:
./include:
myfunc.h
./src:
main.cpp myfunc.cpp
I want to compile the .cpp sources into .o object files, which should end into ./build folder. Using the GNUmake documentation and other sources (e.g. Proper method for wildcard targets in GNU Make), I wrote this makefile:
CXX := g++
CXXFLAGS += -I./include
CXXFLAGS += -Wall
OBJDIR := ./build
SRCDIR := ./src
PROGRAM = release
DEPS = myfunc.h
SRC = $(wildcard $(SRCDIR)/*.cpp)
OBJ = $(patsubst $(SRCDIR)/%.cpp, $(OBJDIR)/%.o, $(SRC))
all: $(PROGRAM)
$(PROGRAM): $(OBJ)
$(CXX) $(CXXFLAGS) -o $(PROGRAM) $(OBJ)
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp $(DEPS)
$(CXX) $(CXXFLAGS) -c $< -o $#
.PHONY: clean
clean:
rm $(PROGRAM) $(OBJ)
But I get the error message: make: *** No rule to make target 'build/main.o', needed by 'release'. Stop.. I tried a lot of different ways but I cannot manage to have my .o files end up in the ./build directory. Instead, everything works if I put them in the root directory of the project. I can also make it work by specifying a rule for each object file, but I'd like to avoid that. What am I missing?
(I am using GNUmake version 4.3)
The problem is here:
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp $(DEPS)
$(CXX) $(CXXFLAGS) -c $< -o $#
See the $(DEPS)? That expands to myfunc.h. The compiler knows where to find that file (or would if this recipe were executed), because you've given it -I./include, but Make doesn't know where to find it (so it passes over this rule).
Add this line:
vpath %.h include
P.S. If you want to be really clean, you can add a variable:
INCDIR := ./include
CXXFLAGS += -I$(INCDIR)
vpath %.h $(INCDIR)

Makefile: dynamic source file names and object directory

Im currently trying to improve the makefile im using to build my c++ project using the sfml-framework. The folder structure of my project currently looks like this:
Src/Header for Header Files
Src/Source for .cpp Files
Bin/ for the .exe
Lib/ for the sfml library
My current makefile:
CC = g++ -g
SRC = Src/Source/
BIN = Bin/
INC = -I Lib/SFML/include/ -I Src/Header/
LIB = -L Lib/SFML/lib/ -lsfml-graphics-d -lsfml-window-d -lsfml-system-d
EXE = Test
SOURCEFILES = $(SRC)Main.cpp $(SRC)Menu.cpp $(SRC)Button.cpp
OBJ = $(SOURCEFILES:.cpp=.o)
all: $(SOURCEFILES) $(EXE)
$(EXE) : $(OBJ)
$(CC) -o $(BIN)$(EXE).exe $(OBJ) $(LIB)
.cpp.o:
$(CC) -c $< $(INC) -o $#
This makefile works fine, however there are a few things i would like to improve but could not get to work.
It's currently nessecary to add all cpp files manually to the list of source files. Since the project is most likely going to grow fast in terms of file count and i kind of want to split the source files into different subdirectories this is going to be a mess very soon. I tried to get all cpp files in a directory with $(wildcard Src/Source/*.cpp) instead of listing them individually but it failed to even execute the makefile. What am i missing there?
With my current makefile all .o files are placed at the same location as the .cpp file which is also something i dont really want. Is there a way to output all .o files in a extra \obj\ directory and link it into the .exe from there?
Also since this is the first time im writing a makefile if there are some general improvements to my approach any advice is appreciated aswell.
wildcard should work:
SOURCEFILES = $(wildcard $(SRC)/*.cpp)
But if you plan to have your source files in various subdirectories of Src/Source/, it will not work that well. Use the find utility instead, thanks to the shell make function. And yes, you can store all your object files in a separate directory:
CC = g++ -g
SRC = Src/Source/
OBJ = Obj/
BIN = Bin/
INC = -I Lib/SFML/include/ -I Src/Header/
LIB = -L Lib/SFML/lib/ -lsfml-graphics-d -lsfml-window-d -lsfml-system-d
EXE = $(BIN)Test.exe
SOURCEFILES = $(shell find $(SRC) -type f -name *.cpp)
OBJECTFILES = $(patsubst $(SRC)%.cpp,$(OBJ)%.o,$(SOURCEFILES))
all: $(SOURCEFILES) $(EXE)
$(EXE): $(OBJECTFILE)
$(CC) -o $# $^ $(LIB)
$(OBJ)%.o: $(SRC)%.cpp
mkdir -p $(dir $#)
$(CC) -c $< $(INC) -o $#
Note that I also modified your EXE definition such that the corresponding rule is a real files-to-file make rule and uses the $# and $^ automatic variables.
I'm kinda suprised that wildcard doesn't work for you, any error codes you could share?
Usually I write my SRCS and OBJS variables like this:
SRCS = $(wildcard src/*.cpp) \
$(wildcard test/*.cpp)
OBJS = $(patsubst %.cpp,$(BINDIR)/%.o,$(SRCS))
And to build your object files into another directory you could write something like this:
$(BINDIR)/%.o: %.cpp
$(CXX) $(CXXFLAGS) $(INCLUDES) -c $< -o $#

Handling Makefile dependencies in multiple subdirectories and outputting to seperate subdirectory

I've been reading through posts about Makefiles that use subdirectories, but can't seem to put all the pieces together properly. I have the following file structure:
program
|
- src
|
- include
|
- build
|
- bin
|
- Makefile
All my sources (.cpp) are in program/src/, all my headers (.hpp) are in program/include, I want all my object files and dependency files put into program/build, and I want my binary placed into program/bin. The following is what I currently have in my Makefile:
CXX = g++
BIN_DIR = bin
TARGET = $(BIN_DIR)/coreint
BUILD_DIR = build
SRC_DIR = src
INC_DIR = include
CXXFLAGS = -Wall -g
# Get all source files
SRCS := $(shell find $(SRC_DIR) -name *.cpp)
# Get all object files by replacing src directory with build directory and replace extension
OBJS := $(subst $(SRC_DIR), $(BUILD_DIR), $(SRCS:%.cpp=%.o))
# Get all depend files by replacing extensions
DEPS := $(OBJS:.o=.d)
# Get all includes by searching include directory
INCS := $(shell find $(INC_DIR) -name *.hpp)
# Append -I to the front of each include
INCS := $(foreach d, $(INCS), -I$d)
# Using VPATH to find files in src/ include/ and build/
VPATH = $(SRC_DIR):$(INC_DIR):$(BUILD_DIR)
all: $(TARGET)
$(TARGET): $(OBJS)
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) -o $(TARGET)
# Build object files and put in build directory
$(BUILD_DIR)%.o: %.cpp
$(CXX) $(CXXFLAGS) -c $< -o $#
# Place dependency files in build directory
# automatically generate dependency rules
$(BUILD_DIR)%.d: %.cpp
$(CXX) $(CXXFLAGS) -MF"$#" -MG -MM -MD -MP -MT"$#" -MT"$(OBJS)" "$<"
# -MF write the generated dependency rule to a file
# -MG assume missing headers will be generated and don't stop with an error
# -MM generate dependency rule for prerequisite, skipping system headers
# -MP add phony target for each header to prevent errors when header is missing
# -MT add a target to the generated dependency
.PHONY: clean all
clean:
rm -f $(OBJS) $(DEPS) $(TARGET)
-include $(DEPS)
When I run make, I get the following error:
make: *** No rule to make target `build/assign.o', needed by `bin/coreint'. Stop.
Where assign.o is the first file in the build directory. Thank you in advance.
I was simply missing a '/' after my BUILD_DIR:
# Build object files and put in build directory
$(BUILD_DIR)/%.o: %.cpp
$(CXX) $(CXXFLAGS) -c $< -o $#

Makefile with sub-directories

I am trying to write a makefile for a C++ project, divided into directories:
makefile
src – (all the .cpp files)
include (all the .h files)
obj (all the .o files)
bin (create the executable there)
I've read a lot about the subject but either it is too simple and they list the files manually or it is too complicated and I am lost.
I tried to write the makefile in many different ways and this is the last one:
CC = g++
CFLAGS = -std=c++11 -c -g -Wall
TARGET = bin/evolveIt
LINKER = g++ -o
# linking flags here
LFLAGS = -Wall -I. -lm
# change these to set the proper directories where each files shoould be
SRCDIR = src
OBJDIR = obj
HDIR = include
BINDIR = bin
SOURCES := $(wildcard $(SRCDIR)/*.cpp)
INCLUDES := $(wildcard $(HDIR)/*.h)
OBJECTS := $(SOURCES:$(SRCDIR)/%.cpp=$(OBJDIR)/%.o)
rm = rm -f
$(BINDIR)/$(TARGET): $(OBJECTS)
#$(LINKER) $# $(LFLAGS) $(OBJECTS)
#echo "Linking complete!"
$(OBJECTS): $(OBJDIR)/%.o : $(SRCDIR)/%.cpp
#$(CC) $(CFLAGS) -c $< -o $#
#echo "Compiled "$<" successfully!"
.PHONEY: clean
clean:
But now I have this error:
src/PopulationManager.cpp:4:31: fatal error: PopulationManager.h: No such file or directory
#include "PopulationManager.h"
^
compilation terminated.
Makefile:28: recipe for target 'obj/PopulationManager.o' failed
make: *** [obj/PopulationManager.o] Error 1
I know that I have to use -I when the headers are in a different directory, but it is already in the CFLAGS and LFLAGS and it doesn't change anything if I put it directly in INCLUDES like this:
INCLUDES := -I $(wildcard $(HDIR)/*.h)
There is no error in the program itself, it compiled fine before I put into different directories. The point of this makefile was to avoid writing relative paths in my source files like
include "include/PopulationManager.h"
Any idea of what's wrong with this makefile?

Makefile, find sources in src directory tree and compile to .o in build file

I'm currently trying to re-write a makefile for a project that I've inherited to make the source tree neater and easier to work with. At the moment the source tree is something like this:
Project/
----bin/
----build/
----include/
----main.h
----part1.h
----part2.h
----part3.h
----src/
----main.cpp
----part1.cpp
----Subdir/
----part2.c
----Subdir2/
----part3.cpp
What I want is a rule in my makefile that will find all of the .cpp and .c files in my src directory and compile them to a flat directory of objects in the build directory. At the moment I have the following in my makefile but this seems to miss a number of the cpp files:
BUILDDIR = build
$(BUILDDIR)/%.o : src/**/%.cpp | $(BUILDDIR)
$(BUILDDIR)/%.o : src/%.cpp | $(BUILDDIR)
$(CXX) $(CFLAGS) -c $< -o $# $(INCS)
$(BUILDDIR)/%.o : src/**/%.c | $(BUILDDIR)
$(BUILDDIR)/%.o : src/%.c | $(BUILDDIR)
$(CC) $(CFLAGS) -c $< -o $# $(INCS)
At the moment when I run make -n it seems that it has detected main.cpp and part1.cpp but none of the ones in subdirectories. Make then goes on to try and load the files according to later rules in the Makefile.
Due to the number of files in the project I'd rather not write a list of them manually but if it comes to that I might have to.
You can explicitly define directories with source files. For example:
DIRS = src src/subdir1 src/subdir2
SEARCHC = $(addsuffix /*.c ,$(DIRS))
SEARCHCPP = $(addsuffix /*.cpp ,$(DIRS))
SRCS = $(wildcard $(SEARCHC))
SRCS += $(wildcard $(SEARCHCPP))
And to let make find your sources files add to your Makefile:
vpath %.c $(DIRS)
vpath %.cpp $(DIRS)
I am also using special target to check my Makefile:
help:
#echo 'Sources:'
#echo $(SRCS)
Make's wildcard function could be of use to you here.
See also
Sources from subdirectories in Makefile