Makefile with directories - c++

My Makefile was fine. However, now I want to have a folder named "Makefile" and a folder named "main", where the first will contain my Makefiles and the second will contain files that are meant to be the main() of my my project, k-d GeRaF.
For now, the header files lie in the same folder. That folder also contains Makefile folder and main folder.
Here is my makefile (have tried many combinations, this is the last attempt):
OBJS = main_par_auto.o
SOURCE = ../main/main_par_auto.cpp
HEADER = ../Division_Euclidean_space.h ../Find_diameter.h ../Find_k_max.h ../Householder.h ../IO.h ../Mean_variance.h ../Point.h ../Random_generator.h ../Random_kd_forest.h ../Tree.h ../Auto_random_kd_forest.h
OUT = geraf
CXX = g++
FLAGS = -pthread -std=c++0x -DRKD_PAR -O3 -Wall
all: $(OBJS)
$(CXX) $(OBJS) -o $(OUT) $(FLAGS)
# create/compile the individual files >>separately<<
main_par_auto.o: main_par_auto.cpp
$(CXX) -c ../main/main_par_auto.cpp $(FLAGS)
.PHONY : all
# clean house
clean:
rm -f $(OBJS)
and I am getting this error:
make: *** No rule to make target `main_par_auto.cpp', needed by `main_par_auto.o'. Stop.
I am executing this command: make -f Makefile/Makefile_par_auto in order to compile.
What am I missing please?
This is the big picture ( literally :) )

The paths in the Makefile have to be relative to the working directory (the directory from which you run make), not to the directory that contains the Makefile. With
main_par_auto.o: main/main_par_auto.cpp
$(CXX) -c main/main_par_auto.cpp $(FLAGS)
you should get the expected results.
Note that it is very unusual to expect a user to invoke make this way. Normally, you'd expect to have a Makefile in the directory where you call make (that may or may not go on to use other makefiles in other directories).

Related

Do I need to declare header files or cxx files or both in a make file?

I read a good tutorial about makefiles, but got a bit confused when things became more complex.
I restructured my workspace Folder and added subfolder: Here is an image of my workspace folder:
I tried to edit the makefile, but still don't succeed making it compile my files.
Do I only need to declare header files in make files or do I need both, header and cxx files?
In the makefile I declared how to build a release and a debug build. I tried to say: create the debug .o files in the debug folder and link them together in debug to an executable called exefile. Since I added the subfolders include and src this got messed up and I do not know how to edit the makefile properly now.
Here is the code of the makefile:
#Compiler Flags#
CC = g++
CFLAGS = -Wall -Werror -Wextra
HDIR = include
#Project Files#
SRCS = src/main.cxx src/ex05_01.cxx src/ex05_02.cxx
OBJS = $(SRCS:.cxx=.o)
EXE = exefile
#Debug Build Settings#
DBGDIR = debug
DBGEXE = $(DBGDIR)/$(EXE)
DBGOBJS = $(addprefix $(DBGDIR)/, $(OBJS))
DBGCFLAGS = -g -O0 -DDEBUG
#Release Build Settings#
RELDIR = Release
RELEXE = $(RELDIR)/$(EXE)
RELOBJS = $(addprefix $(RELDIR)/, $(OBJS))
RELFLAGS = -g -O0 -DNDEBUG
.PHONY: all clean debug prep release remake
#default build
debug: $(DBGEXE)
$(DBGEXE): $(DBGOBJS)
$(CC) $(CFLAGS) $(DBGCFLAGS) -o $(DBGEXE) $^
$(DBGDIR)/%.o: %.cxx
$(CC) -c $(CFLAGS) $(DBGCFLAGS) -o $# $<
# Release rules
release: $(RELEXE)
$(RELEXE): $(RELOBJS)
$(CC) $(CFLAGS) $(RELCFLAGS) -o $(RELEXE) $^
$(RELDIR)/%.o: %.cxx
$(CC) -c $(CFLAGS) $(RELCFLAGS) -o $# $<
# Other rules
prep: mkdir -p $(DBGDIR) $(RELDIR)
remake:
clean all
clean:
rm -f $(RELEXE) $(RELOBJS) $(DBGEXE) $(DBGOBJS)
Thank you for your help!
EDIT: I forgot to post the error message of make:
*** No rule to make target debug/main.o', needed bydebug/exefile'. Stop.
You should include rules for the header file dependencies as well. Assuming that main.cxx depends on ex05_01.h, when ex05_01.h changes, you would want main.cxx to be recompiled. Something like this would do the job:
main.o: ex05_01.h ... (add more headers if you have)
(repeat for all .o files)
Your debug and release builds only differ by a few things: an output folder DIR and a DEBUG/NDEBUG define flag in FLAGS. To avoid duplicating all the settings, you could refactor and make common targets, and then switch between your settings with a conditional over a variable, for example, if you run make like so:
make BUILD=REL <target>
you will get a variable BUILD defined with "REL" value, then you can use ifeq (see https://www.gnu.org/software/make/manual/html_node/Conditional-Example.html#Conditional-Example ) to set your DIR and FLAGS accordingly.

Makefile in sub-directory

I am trying to write a makefile in a subdirectory of my eclipse makefile project.
MyProject \
test.cpp
Build\
Makefile
I am also trying to create a generic makefile. I am having trouble defining the targets since the build is not happening in the same directory as the source.
CC = g++
CC_FLAGS = -g3
EXEC = test
SOURCEDIR = ..
SOURCES = $(shell find $(SOURCEDIR) -name '*.c' -o -name '*.cpp')
OBJECTS = $(addsuffix .o,$(subst ../,,$(SOURCES)))
.DEFAULT_GOAL = all
$(EXEC): $(OBJECTS)
$(CC) $(OBJECTS) -o $(EXEC)
%.o: %.cpp
$(CC) -c $(CC_FLAGS) $< -o $#
.PHONY: clean
clean:
rm -f $(EXEC) $(OBJECTS)
.PHONY: all
all: $(EXEC)
Right now when I build I get the error...
make all
make: *** No rule to make target 'test.cpp.o', needed by 'test'. Stop.
Can anyone tell me why this is not working or recommend a better approach.
If you change your dependency from object to source as follows:
%.cpp.o: $(SOURCEDIR)/%.cpp
it seems to work.
In general I would prefer to NOT do anything in a build dir, because I personally expect a build dir is a temporary dir which can be removed completely for distribution which is not the case if the Makefile resists there. But this is a matter of taste.
Also I do not prefer to use all c/cpp you find as objects/sources in the make process. If you need to add files for different variants in your projects, you enter a nightmare to change all these things later.
And also as a hint: Typically objects are <basename>.o and not <basename>.cpp.o
And another one:
Users expect that the clean target also remove the executable. If not, you will never see a rebuild by simply do make clean; make, because the executable is in place and all dependencies are fulfilled.

Make and c++ files, "includes" in the cpp

This is my current makefile:
# Compiler #
CXX = g++
DEBUG = -g
LFLAGS =
CXXFLAGS = -Wall
# Directories #
SRCDIR = src/
INCDIR = include/
BUILDDIR = build/
BINDIR = bin/
# Objects #
OBJ_NAMES = main.o dfa.o dfaException.o state.o
OBJS = $(addprefix $(BUILDDIR), $(OBJ_NAMES))
# Output #
NAME = pract3
TARGET = $(BINDIR)pract3
# Clean #
ifeq ($(OS),Windows_NT)
RM = del /q /s $(BUILDDIR:/=\)*.o $(BINDIR:/=\)$(NAME)*
else
RM = rm -rf $(BUILDDIR)*.o $(TARGET)*
endif
# Files #
$(TARGET): $(OBJS)
$(CXX) $(CXXFLAGS) $(LFLAGS) $(OBJS) -o $(TARGET)
$(BUILDDIR)%.o: $(SRCDIR)%.cpp
$(CXX) $(CXXFLAGS) $(LFLAGS) -c $< -o $#
clean:
$(RM)
And this is my project tree:
Porject/
bin/
build/
doc/
...
include/
connection.hpp
dfa.hpp
dfaException.hpp
state.hpp
src/
dfa.cpp
dfaException.cpp
main.cpp
state.cpp
Makefile
Readme
Now, I'm having three "problems".
First I want my makefile to create the bin and build directories just in case they aren't. I guess I just have to use:
mkdir $(BUILDDIR)
mkdir $(BINDIR)
But where should I put them ? And also, how can I prevent mkdir and rm (or del in windows) messages like "Cant find ..." or "x directory already exists ... "
Second, I'm guessing I can read the objects name from src/ (converting the .cpp to .o), but how can I read the file names from a directory ?
Last, I have one template class: connection.hpp (all functions are in the header). This file is included in state.hpp using: #include "../include/connection.hpp". I ran make one time with all correct and then I purposely make a syntax error in connection.hpp. Then I ran make again, but It only compiled the target file using the .o files in build without any error. Everytime I want to edit connection.hpp I have to use make clean and then make. Is there any better way to do this ?
If you need a directory to exist before you can proceed, simply put
mkdir -p ${DIRECTORY}
before you need it in your rule. If the directory already exists, mkdir -p will happily do nothing.
Likewise, if you use rm -f FILE, it should not complain if FILE does not exist in the first place.
There is no portable way to create a variable that holds the names of all files in a directory. But you are already using GNU Make features anyway, so you can just use
SOURCES = $(wildcard ${SRCDIR}/*.cpp)
and then
OBJECTS = $(SOURCES:.cpp=.o)
to transform them into object file names. You'll probably want to replace the leading directory name as well, I guess.
You didn't list any *.hpp files as prerequisites in your make file. You can either manually add them like
foo.o: foo.cpp bar.hpp baz.hpp
but that becomes unpleasant very quickly. Another trick is to use the compiler to tell you the headers (transitively) #included by a file. If you are using GCC, you can run
gcc -MM foo.cpp
to have it output above make-file snippet. You can put a pattern rule like the following
%.deps: %.cpp
${CXX} -MM ${CPPFLAGS} $< > $#
into your make-file and then include the generated *.deps files.
include $(SOURCES:.cpp=.deps)
GNU Make will be smart enough to first parse the make-file, recognize that the *.deps files don't exist and therefore cannot be included but figure out that there is a rule to generate them. So it will execute that rule and then continue parsing the make-file.
I have learned that trick from Peter Miller's great article Recursive Make Considered Harmful which is a good read if you want to learn how to write good make-files.

Unable to find headers with make

I have a (fairly simple) makefile adapted from here that I am attempting to use to build a project on Ubuntu. The project tree is fairly simple: Makefile is in the root project directory, and there are src/, include/, build/, and bin/, where source code, header files, object files, and executables are stored, respectively.
When I run make from the root directory of the project, I get the following error message:
Linking...
g++ src/Main.cpp src/Foo.cpp -o bin/runner
src/Main.cpp:1:19: fatal error: Foo.hpp: No such file or directory
#include "Foo.hpp"
^
compilation terminated.
src/Foo.cpp:1:19: fatal error: Foo.hpp: No such file or directory
#include "Foo.hpp"
^
compilation terminated.
make: *** [bin/runner] Error 1
All that's currently in the project is Main.cpp. which calls two test functions Foo() and Bar() from Foo.cpp, which references a header file Foo.hpp. Here is the makefile:
CC := g++ # This is the main compiler
SRCDIR := src # Directory for source code
BUILDDIR := build # Directory containing all object files, which are removed on "make clean"
TARGET := bin/runner # bin/runner contains the main executable for project
# bin/ contains all other executables in the project (such as tests)
SRCEXT := cpp # File extension of source code
# Look for all the source files in SRCDIR with the file extension specified above
SOURCES := $(shell find $(SRCDIR) -type f -name *.$(SRCEXT))
# Name all object files the same root name as the source files from which they came, but add a .o extension to the end
OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.o))
# The -g flag specifies that debugging information should be produced in the native format of the OS
CFLAGS := -g -Wall
# Various flags for libraries that might need to be linked
INC := -I include # Ensures that all header files (in the include/ folder) are accessible for build
# Show the components that are currently being compiled/linked
# Also, this is the main procedure for make: The TARGET is built from the objects, and
# object files are built from source
$(TARGET): $(OBJECTS)
#echo " Linking..."
#echo " $(CC) $^ -o $(TARGET)"; $(CC) $^ -o $(TARGET)
$(BUILDDIR)/%.o: $(SRCDIR)/%.$(SRCEXT)
#mkdir -p $(BUILDDIR)
#echo " $(CC) $(CFLAGS) $(INC) -c -o $# $<"; $(CC) $(CFLAGS) $(INC) -c -o $# $<
# Directives for "make clean" which cleans all object files out of the build/ folder
clean:
#echo " Cleaning...";
#echo " $(RM) -r $(BUILDDIR) $(TARGET)"; $(RM) -r $(BUILDDIR) $(TARGET)
# Destroys everything in the build/ and bin/runner/ folders. Does not clean test executables.
.PHONY: clean
What am I missing here in order to get the header files to be properly linked?
EDIT: Here is the new makefile, and the current output:
# This is the main compiler
CC := g++
# Directory for source code
SRCDIR := src
# Directory containing all object files, which are removed on "make clean"
BUILDDIR := build
# bin/runner contains the main executable for project
# bin/ contains all other executables in the project (such as tests)
TARGET := bin/runner
# File extension of source code
SRCEXT := cpp
# Ensures that all header files (in the include/ folder) are accessible for build
INC := -I/include
# Look for all the source files in SRCDIR with the file extension specified above
# SOURCES := $(shell find $(SRCDIR) -type f -name *.$(SRCEXT))
SOURCES := $(wildcard $(SRCDIR)/*.$(SRCEXT))
# Name all object files the same root name as the source files from which they came, but add a .o extension to the end
# OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.o))
OBJECTS := $(addprefix $(TARGET)/, $(notdir $(SOURCES:.cpp=.o)))
# The -g flag specifies that debugging information should be produced in the native format of the OS
CFLAGS := -g -Wall
# Various flags for libraries that might need to be linked
LIB := #-pthread -lmongoclient -L lib -lboost_thread-mt -lboost_filesystem-mt -lboost_system-mt
# Show the components that are currently being compiled/linked
# Also, this is the main procedure for make: The TARGET is built from the objects, and
# object files are built from source
$(TARGET): $(OBJECTS)
#echo " Linking..."
$(CC) $^ -o $(TARGET)
# #echo " $(CC) $^ -o $(TARGET) $(LIB)"; $(CC) $^ -o $(TARGET) $(LIB)
$(BUILDDIR)/%.o: $(SRCDIR)/%.$(SRCEXT)
#mkdir -p $(BUILDDIR)
$(CC) $(CFLAGS) $(INC) -c -o $# $<
# Directives for "make clean" which cleans all object files out of the build/ folder
clean:
#echo " Cleaning...";
#echo " $(RM) -r $(BUILDDIR) $(TARGET)"; $(RM) -r $(BUILDDIR) $(TARGET)
# Tests
# tester:
# $(CC) $(CFLAGS) test/tester.cpp $(INC) $(LIB) -o bin/tester
# Spikes
# ticket:
# $(CC) $(CFLAGS) spikes/ticket.cpp $(INC) $(LIB) -o bin/ticket
# Destroys everything in the build/ and bin/runner/ folders. Does not clean test executables.
.PHONY: clean
Output:
[scott]> make
make: *** No rule to make target `bin/runner/Foo.o', needed by `bin/runner'. Stop.
tl;dr
Don't put end-of-line comments on variable assignments in make. It doesn't work the way you might expect.
Explanation
Your makefile isn't running the steps you expect it is.
You shouldn't be seeing Linking... for the compilation step.
make shouldn't be attempting to create the target from the source .cpp files.
You should be seeing your INC and CFLAGS values on the compilation line (but you are getting linking output so obviously aren't seeing them).
That's why your header can't be found by the way, your linking line doesn't have -I on it anywhere.
The reason that's happening is because make is applying the wrong rule.
make is applying the wrong rule because your variables are being set incorrectly.
Your variables are being set incorrectly because your variables have values you don't expect.
The makefile you started from had errors the author wasn't aware of.
make is not always very smart.
When you write
FOO := some value # comment
you expect FOO to have the value some value but make sees things differently.
make gives it the value some value since it can't tell the difference between the space between some and value and the space after value and before the comment.
So when you run your shell command (with *.$(SRCEXT) unquoted) the shell just ignores the trailing spaces). (Try quoting *.'$(SRCEXT)' and see what you get.)
However when you then try to $(SOURCES:=.$(SRCEXT)=.o) make doesn't drop the spaces and you have actually written $(src/Main.cpp src/Foo.cpp:=cpp =.o) which, you may notice, is a pattern that doesn't actually match.
As a result $(OBJECTS) gets the unmodified value of $(SOURCES) and "confuses" the $(TARGET): $(OBJECTS) line later causing make to skip your compilation target.
(Oh, also, that's why your linking line has a million spaces between g++ and the first source file.)
Oh, also, you don't need to shell out for find there unless your src/ directory has sub-directories of its own (and even then not with some make magic) because $(wildcard $(SRCDIR)/*.$(SRCEXT)) will work just fine (and also would have failed earlier I believe given this problem).
Define an environment variable that has . (current working directory) first, then ./include (not just include subdirectory but as ,/include and rest of the INCLUDE dirs that you might already have because of the compiler or other software requirement)
set INCLUDE :=.:./include:$INCLUDE
Alternately, use:
INC := -I. -I./include
gcc -I option is as: -I dir
Adds the directory dir to the list of directories to be searched for header files. Directories named by '-I' are searched before the standard system include directories. If the directory dir is a standard system include directory, the option is ignored to ensure that the default search order for system directories and the special treatment of system headers are not defeated

How do I write a smart makefile?

I'm new to linux and new to makefiles so I'm a little stumped at this point. I've been staring the make manual for an hour now and figured I would just ask:
I want to create a makefile for a relatively small project, whose source files are in proj/src/, and within subdirectories of that location. I have written a makefile at proj/makefile and want to use it to gather up all the source files, find their dependencies, and compile the result into proj/build/. Here is what I've written:
# here are my files and directories (there are also header files that are not
# listed here, but these are referred to from within the .cpp files with
# respect to the proj/src directory)
# proj/makefile
# proj/src/
# proj/src/main.cpp
# proj/src/dir1/
# proj/src/dir1/source1.cpp
# proj/src/dir2/
# proj/src/dir2/source2.cpp
# proj/build/
srcDir = src/
buildDir = build/
# This is a list of all the object files (can I get this programatically?)
objects = main.o source1.o source2.o
all: prog
# Here I want to compile all source (.cpp) files from src/ and all of its subdirectories, and to find the dependencies I want to call g++ -MM to automatically generate the list:
%.o: %.cpp
$(CXX) $(CXXFLAGS) -MM -I $(srcDir)
clean:
rm -rf *o $(buildDir)/prog
This is far from functional but I wanted to give it ago before asking. Running this gives
make: * No rule to make target main.o', needed byprog'. Stop.
So presumably my attempt at automatically writing the object files failed. If someone could give me some direction that would be great, I'm hoping that between the comments and code you can make out the intention.
EDIT: I have now tried the following:
SHELL := /bin/bash
srcDir = src
buildDir = bin
sources := $(shell find $(srcDir) -name *.cpp)
objects := $(sources:%.cpp=%.o)
-include $(sources:%.cpp=%.d)
# This is a list of all the object files (can I get this programatically?)
all: prog
prog: $(objects)
g++ $(objects) -o $(buildDir)/prog
# Here I want to compile all source (.cpp) files from src/ and all of its subdirectories, and to find the dependencies I want to call g++ -MM to automatically generate the list:
%.o: %.cpp
$(CXX) $(CXXFLAGS) -MMD -MP -c -I $(srcDir)
clean:
rm -rf *o $(buildDir)/hello
But when I run this I get the following error:
g++ -MMD -MP -I src
g++: fatal error: no input files
compilation terminated.
make: *** [src/core/Cell.o] Error 1
It wants to build main.o from main.cpp, but there is no main.cpp at the top level. You could specify the full paths of the object files, if they are to be built alongside the source files:
objects = $(srcDir)/main.o $(srcDir)/dir1/source1.o $(srcDir)/dir2/source2.o
can I get this programatically?
I do it using gnumake's shell function:
SHELL := /bin/bash
sources := $(shell find $(srcDir) -name *.cpp)
objects := $(sources:%.cpp=%.o)
to find the dependencies I want to call g++ -MM to automatically generate the list
Use -MMD to generate dependency files as well as compiling. It's also a good idea to specify -MP here - that makes sure the dependencies are correctly updated when you remove a header. Given the variables defined above, you can include the dependency files with
-include $(sources:%.cpp=%.d)