Makefile in sub-directory - c++

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.

Related

Using makefile arguments without foo=

I have a makefile I use to compile a single file. When I need to pass an argument, I use target=targetFile.
The script takes the argument, looks for the file (within the same directory) that has the same value as the argument and compiles it.
I use this for compiling problems from uhunt and uva, which use a single c++ file. So I dont' need multiple makefiles for multiple source files. Single makefile for multiple source files is the reason I made the makefile.
Here's the code I have so far
OBJS = $(target).o
CC = g++
CFLAGS = -Wall -g -std=c++11
INCLUDE = -I./$(target)
#default command to run
all : Main-$(target) clean run
#compile and build
Main-$(target) : $(OBJS)
$(CC) $(CFLAGS) $^ -o $#
%.o : %.cpp
$(CC) -c $(CFLAGS) $<
#remove object and any other garbage files.
clean:
rm -rf -d $(target).o *~ *% *# .#*
#remove the compiled file
clean-all:
$(clean) rm Main-$(target)
#run the compiled file
run:
./Main-$(target)
The command I use to compile is,
make target=sourceFile
Also I don't include the file extension, I have all my source file extensions to be cpp
What I want in the end is:
make sourceFile
Just a side note, for using the command clean and clean-all, I use
make target=sourceFile clean
make target=sourceFile clean-all
I'd prefer if I can use:
make sourceFile clean
make sourceFile clean-all
You may use common Makefile variable MAKECMDGOALS that contains all targets passed to make.
Please try this variant
CC = g++
CFLAGS = -Wall -g
MAKECMDGOALS := $(filter-out clean, $(MAKECMDGOALS))
.PHONY: $(MAKECMDGOALS)
$(MAKECMDGOALS):
$(CC) $(CFLAGS) $#.c -o Main-$#
clean:
rm -f *.o
Here the lines
$(MAKECMDGOALS):
$(CC) $(CFLAGS) $#.c -o Main-$#
will generate separate build targets for each word in MAKECMDGOALS.
Note, we need this Makefile to know that 'clean' is a target for removing stuff, but not to attempt build Main-clean. This why we remove clean from MAKECMDGOALS using filter-out function.
So if we run make a b clean, the build system will generate automatically targets for building Main-a and Main-b and then use already written clean target
Disclaimer -- this is a non-standard use of Make, and will therefore open up all kinds of corner cases, so I don't recommend it. This is better suited for a shell script calling make. That being said... it is an interesting question.
You can't do make xxx clean, and not have it try to build xxx (unless you do some really nasty cludge using recursive make, but I won't go there). You could do something like make clean-xxx though, as follows:
%:Main-%
Main-%:%.cpp
$(CC) $(CFLAGS) $< -o Main-$#
clean-%:
rm Main-$*
Notice that %-clean has a shorter stem, and therefor takes precedence over the % if the make target starts with clean-.

C++ makefile building multiple dll and project structuring

I have tried searching for an answer but to no avail, so given that my project has got the following structure
makefile
./src
strings.cpp
networking.cpp
./bin
strings.dll
networking.dll
./build
strings.o
networking.o
./include
strings.h
networking.h
./lib
boost
I am very new to Makefiles and from the research I have done so far I have managed to get this together (not very complicated, I know)
CC = g++
SRC = src/strings.cpp
OUT = bin/strings.dll
OBJ = build/strings.o
INC= -I include
all: strings.dll
strings.dll: strings.o
$(CC) -shared -o $(OUT) $(OBJ)
strings.o: $(SRC)
$(CC) $(INC) -DBDLL -c $(SRC) -o $(OBJ)
The issues/questions I have are
1- It always goes through the whole compilation process, even when I have not changed the source code ?
2- How could I make things more 'effective' ? I saw examples of people using wildcards and such, but I had difficulty following along. Could I use wildcards to begin with since I want separate dlls for each target ?
3 - Lets say I introduced algorithms.h and algorithms.cpp what would be the recommended way of including that in the build ?
Thanks for any help, really appreciate it
First. Whole compilation process goes because make search for target "strings.dll" but build bin/strings.dll. So if you replace it to
bin/strings.dll: strings.o
$(CC) -shared -o $(OUT) $(OBJ)
bin/strings.o: $(SRC)
$(CC) $(INC) -DBDLL -c $(SRC) -o $(OBJ)
build of targets (bin/strings.o and bin/strings.dll) will be performed only if prerequisite is changed.
Second - basically wildcards are used for search all files inside the directory something like this: $(whildcard *.cpp) evaluates to all cpp file inside the current directory. So you can write something like this:
all_sources = $(wildcard *.cpp)
all_objects = $(addprefix bin/,$(all_sources:.cpp=.o))
all: bin/strings.dll
bin/strings.dll: $(all_objects)
<how to build strings.dll from objects>
bin/%.o: %.cpp
<how to build objects inside bin dir from cpp of current dir>
Third - makefile is not build system itself it is just a tool that has domain specific language. You can write your own build system using make. If you want ready build you better to study automake/cmake/... many of them.
Also it is good beginning to start using make tool. Don't stop and you will surprise how much power inside it.

Makefile with directories

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).

(GNU) Make: How does one set up a basic system?

I would like to try to establish a very small system of Makefiles. I have the following set up, but something is not quite right (this has been pieced together from reading a few SO posts about the topic, though somewhat project-specific, and some websites. I must not be catching something fundamental in having a "Makefile" call sub-makefiles.
This is even simpler than having the main Makefile call files in different subdirectories. Here are the following files I have prepared:
Makefile:
all:
$(MAKE) -f ./make_system.mk
$(MAKE) -f ./make_crc.mk
make_system.mk:
G = -g ## debug option
CC = gcc ## compiler
SRCS = source.c sink.c gateway.c
EXES = source sink gateway
OBJS = source.o sink.o gateway.o
CFLG =
LFLG =
LIB = #-lsocket -lnsl -lpthread
all: $(EXES)
%.o: %.c %.h
$(CC) -c $G $(CFLG) $<
source: source.o
$(CC) -o source source.o $(LIB) $(LFLG)
sink: sink.o
$(CC) -o sink sink.o $(LIB) $(LFLG)
gateway: gateway.o
$(CC) -o gateway gateway.o $(LIB) $(LFLG)
clean:
/bin/rm -f core *.o $(EXES) *~
make_crc.mk:
CC = gcc
CFLAGS = -g
LFLAGS =
HDR = crcmode.h
SRC = crcmodel.c crctest.c
OBJ = crcmodel.o crctest.o
EXE = crctest
all: $(EXE)
%.o: %.c %.h
$(CC) -c $(CLFAGS) $<
$(EXE): $(OBJ)
$(CC) $(LFLAGS) $(OBJ) -o $(EXE)
clean:
/bin/rm -f *.o *~ core $(EXE)
How would I set up Makefile to call the smaller sub-makefiles (of type *.mk)? This is a basic but important first step towards working with larger scale makefile systems (there is the manual to consult, though I do not think it has explicit basic examples). If someone who has done this could show me a small Makefile vignette, this would be greatly appreciated (again, this makefile system can exist within the same local directory).
Note: The individual makefiles "make_system" and "make_crc" work fine when they are themselves named "Makefile", but I want to try to call them as separate sub-makefiles with one single overall Makefile.
ADDENDUM (to solution below):
Once I implemented Carl's solution shown below, I realized that you need to always include some form of "make clean" or at least enter at in the command line before calling your Makefile. Otherwise, you see the appropriate output "nothing to be done". This was something I knew before, but neglected to do this time around (easy check: just look at your directory and you will see you have executables in the environment/directory).
I you want to "forward" the target, you'll need to do it explicitly. Something like this example should work (though I can't test easily right now, sorry):
default: all
%:
$(MAKE) -f ./make_system.mk $#
$(MAKE) -f ./make_crc.mk $#

organize project and specify directory for object files in Makefile

Here are my two questions:
I am now learning to manage my code with CVS, and I just want to make a repository for my C++ files, Makefile and bash and python scripts only, not the object files and executables. So I made several subdirectories under my project directory: src, bin, scripts, results and data.
I put C++ files and Makefile under ~/myproject/src, Bash and Python scripts under ~/myproject/scripts and object and executables under ~/myproject/bin. I am hoping only the files under src and scripts will be updated via CVS. I wonder how you organize your projects? Just hope to follow some good habits.
Since I put my C++ files and Makefile into ~/myproject/src and object and executable files into ~/myproject/bin, I have to specify the directories in Makefile. Here is what I am doing
Makefile:
...
BIN_DIR=/home/myproject/bin/
all: $(BIN_DIR)myexecutable TAGS
TAGS: *.cc *.h
etags --members --declarations -l c++ *.cc *.h
$(BIN_DIR)myexecutable: $(BIN_DIR)myobject.o
$(CXX) $(CXXFLAGS) -o $# $^ $(LDFLAGS)
Makefile.depend: *.h *.cc Makefile
$(CXX) -M $(CXXFLAGS) *.cc > Makefile.depend
clean:
\rm -f $(BIN_DIR)myexecutable $(BIN_DIR)*.o Makefile.depend TAGS`
However this will give error
make: *** No rule to make target /home/myproject/bin/myobject.o', needed by /home/myproject/bin/myexecutable'.
How to specify a different directory for object and executable files from C++ files in Makefile?
If you want to learn make, the GNU make manual is very good, both as a reference and a tutorial. You might want to consider using the patsubst command. The following is a chopped down version of one of my own makefiles that uses it:
OUT = bin/csvfix.exe
CC = g++
IDIR = inc
ODIR = obj
SDIR = src
INC = -Iinc -I../alib/inc
LIBS = ../alib/lib/alib.a -lodbc32
_OBJS = csved_atable.o \
csved_case.o \
csved_cli.o \
csved_command.o \
csved_date.o \
OBJS = $(patsubst %,$(ODIR)/%,$(_OBJS))
$(ODIR)/%.o: $(SDIR)/%.cpp
$(CC) -c $(INC) -o $# $< $(CFLAGS)
$(OUT): $(OBJS)
$(CC) -o $# $^ $(CFLAGS) $(LIBS)
strip $(OUT)
clean:
rm -f $(ODIR)/*.o $(OUT)
You can keep your files in different directories if you like, but that isn't necessary. Add a file or directory to the CVS repository once, and CVS will retain it indefinitely. From then on you can update it, check it in, whatever. If you don't add an object file to the repository, CVS won't touch it. If you want to add a whole directory tree, and you're in the habit of keeping objects there, just make clean before you do it.
Make is a wonderful tool, but it has some glaring faults. What you're describing is one of the classic problems: Make is good at using a source there to make something here, but not the other way around. Here are a couple of ways to do what you're trying to do.
A) Run make in your binary directory:
...
all: myexecutable TAGS
myexecutable: myobject.o
$(CXX) $(CXXFLAGS) -o $# $^ $(LDFLAGS)
VPATH = /home/myproject/src
...
cd ~/myproject/bin
make -f ../src/makefile
B) Put the objects on the bin directory by brute force:
$(BIN_DIR)%.o: %.cc
$(CXX) $(CXXFLAGS) -c -o $# $^
This will give you a problem with Makefile.depend, which you can approach several ways.
C) Learn some more advanced Make techniques. You probably shouldn't try this yet.
Your directory structure seems sensible.
I would make an explicit rule for executing the compiler, like
TARGET_DIR=bin
SRC_DIR=src
CXX=g++
CXXFLAGS=
ETC=
OBJS=$(TARGET_DIR)/test.o
all: $(OBJS)
$(TARGET_DIR)/%.o: $(SRC_DIR)/%.cc
$(CXX) -c -o $# $(CXXFLAGS) $(ETC) $<
Use automake and autoconf for building your project.
As for the structure of files just look at any big open-source C++ application. Any KDE application
will do fine for that matter. If you find an application that uses C++ and Python even better.
Why not go for eclipse, which is quite popular and handy for managing large projects. You can make a new project in eclipse, import-export code into the project from other projects, does version control for you as well etc. No need to write your make files, eclipse does it for you with your mentioned preferences in GUI.
If you are involved in a C++ project, just install the CDT plugin over eclipse and your are done.