Makefile: dynamic source file names and object directory - c++

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 $#

Related

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

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.

need help creating a static c++ library using make

I am trying to create a static library based on the file layout given below.
/library
Makefile
/include
.h files
/src
.cpp files
/build
.o files
/lib
.a file
When I run make all with the current code in my makefile given below it gives me the error:
make: *** No rule to make target src/%.cpp', needed bybuild/BaseGfxApp.o'. Stop.
CPP_FILES = $(wildcard src/*.cpp)
OBJ_FILES = $(addprefix build/,$(notdir $(CPP_FILES:.cpp=.o)))
CC_FLAGS = -c -Wall
all: libphoto.a
libphoto.a: $(OBJ_FILES)
ar rcs lib/$# $^
build/%.o: src/%.cpp
g++ $(CC_FLAGS) $# $<
I am fairly new to 'make' and I honestly have no clue where to go from here. I would appreciate some input or help. Thanks!
It could be that you are missing a makefile in your src/ directory.
dont put paths in the rules
%.o: %.cpp
g++ $(CC_FLAGS) $# $<
I think the main problem is you are not giving the proper path to the files you are trying to build. But also you missed some flags for g++. I think the following changes should work (not properly tested).
CPP_FILES = $(wildcard src/*.cpp)
OBJ_FILES = $(patsubst src/%.cpp,build/%.o,$(CPP_FILES))
CXXFLAGS = -Wall
all: prereqs lib/libphoto.a
lib/libphoto.a: $(OBJ_FILES)
ar rcs $# $^
build/%.o: src/%.cpp
g++ -c $(CXXFLAGS) -o $# $<
prereqs:
mkdir -p lib
mkdir -p build
.PHONY: prereqs
clean:
rm $(OBJ_FILES) lib/libphoto.a

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

Single top-level makefile with source subdirectories

Firstly, apologies for my ignorance. I'm sure the answer to my question exists in one of the many existing makefile threads here. However, I have been unable to find one that concisely and clearly answers my specific question without obfuscating the answer with details that aren't relevant to my particular situation.
My code directory has a single top-level source file containing main. The rest of the source files are organised in subdirectories according to logical divisions in the system. The code contains no relative paths in the includes. This means that everything works perfectly if all the code is in a single directory using the following, simple makefile:
CC=g++
CFLAGS=-c
LDFLAGS=
SOURCES=Main.cpp Source1.cpp Source2.cpp Source3.cpp Etc.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=executable
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o $#
.cpp.o:
$(CC) $(CFLAGS) $< -o $#
Until now I have been building my code using the NetBeans IDE. This has helped preserve my make ignorance by generating some vast and overly complicated makefiles on my behalf. Now the time has come to distribute my code for public use so I'm looking to produce a makefile will enable me to distribute the code with the directory structure I have.
Can you help?
Regards,
Enthusastic Amateur.
Take a look at this:
# Source directories separated by space
# Example ./ src1/ src2/
SRCDIR = ./ src/
# Directory where object files will be placed
OBJDIR = obj/
# Include directories separated by space
# Example: include1/ include2/
INCDIR = include/
# Directory where binary file will be placed
BINDIR = bin/
# Name of the result file
TARGET = app
# Compiler
CXX = g++
# Retrive list of the source files
SRC = $(wildcard $(addsuffix *.cpp,$(SRCDIR)))
# Generate list of the object files
OBJ = $(addprefix $(OBJDIR), $(patsubst %.cpp, %.o, $(notdir $(SRC))))
VPATH = $(SRCDIR)
# Compilation flags
CXXFLAGS = -std=c++11 -pthread
$(TARGET) : $(OBJ)
#echo Linking...
#mkdir -p $(BINDIR)
#$(CXX) $(CXXFLAGS) -o $(BINDIR)$# $(OBJ)
$(OBJDIR)%.o : %.cpp
#echo Compiling $< in $#...
#mkdir -p $(OBJDIR)
#$(CXX) $(CXXFLAGS) $(addprefix -I,$(INCDIR)) -c -o $# $<
clean :
#$(RM) -r $(OBJDIR)
#$(RM) -r $(BINDIR)
Here you can provide multiple source directories.
And "everything works perfectly" as well if the code is in multiple directories, using the same makefile you already have. No changes needed.

Make with Autodependencies for C++

I have looked, and found a few answers that look like they're related to this question, but none seem to help.
It is the usual story - I have a folder of .hpp and .cpp files which I'd like to compile to .o files, and then only have files recompiled when files they depend on have been changed.
My current makefile is:
SRCS = $(shell find ../Includes/ -name "*.cpp")
DEPS = $(SRCS:.cpp=.d)
OBJS = $(SRCS:.cpp=.o)
all: $(DEPS) $(OBJS)
# Create the dependency files
%.d : %.cpp
clang++ -MM $< -o $# -c -std=c++11
# Include the dependency files
include $(DEPS)
# Compile the source files
%.o : %.cpp
clang++ -c -Wall -std=c++11 $< -o $#
I've run this a few times (so the dependency files exist before I run make, and should definitely exist when I include them). I've also tried adding %.d to the dependancies of %.o.
Basically all that happens at the moment is that 'touch'ing a .cpp causes the .o and .d files to be regenerated, and touching a .hpp file (that is listed in the .d files for other files) does nothing.
Example Dependency File:
SomeFile.o : ../Includes/SomeFile.cpp \
../Includes/SomeFile.hpp ../Includes/SomeOtherFile.hpp
Apart from the path issue, I find it more natural to create the dependencies along the way, i.e. with the -MD or -MMD flags. That way you don't need a rule to update the dependency file.
CPPFLAGS += -MMD
TARGET := hello
.DEFAULT: all
all: $(TARGET)
SRCS := $(shell find . -type f -name "*.cpp")
OBJS := $(SRCS:.cpp=.o)
DEPS := $(SRCS:.cpp=.d)
hello: $(OBJS)
$(LINK.cc) -o $# $^
-include $(DEPS)
It turns out that I was creating rules for:
SomeFile.o : ...
Whereas I needed a rule for:
../Includes/SomeFile.o : ...
Thanks to NovaDenizen who set me on the right path.