I have a makefile which keeps on rebuilding the c++ source everytime i do compilation. I figured out the reason is i am dumping object files in a separate directory.
One line from make file is :
$(CPP_COMPILER) $(COMPILE_FLAGS) $(RELEASE_OPT_FLAGS) -c Test.cpp $(INCLUDE_PATH) -o objfiles/$(OUTDIR)/Test.o
Can i put some rule with which make first check this dir (objfiles) and if not needed do not re-build the source everytime?
Thanks for your help.
You should make the rule itself refer to the correct path:
objfiles/$(OUTDIR)/Test.o: Test.cpp
$(CPP_COMPILER) $(COMPILE_FLAGS) $(RELEASE_OPT_FLAGS) -c Test.cpp $(INCLUDE_PATH) -o objfiles/$(OUTDIR)/Test.o
If you still want Test.o as the makefile target, you can easily add one then:
Test.o: objfiles/$(OUTDIR)/Test.o
Related
I have two files "create-exercise.cpp" and "exercise.hpp". I want to write a makefile to use gnu++17 and g++ to compile them. exercise.hpp is included in create-exercise.cpp. I only want to get a binary out of create-exercise.cpp. the command I would use is g++ -std=gnu++17 create-exercise.cpp -o create-exercise and it works well. I tried using the following in a make file.
CXXFLAGS=-Wall -std=gnu++17
create-exercise: create-exercise.cpp exercise.hpp
but that generated the following g++ -Wall -std=gnu++17 create-exercise.cpp exercise.hpp -o create-exercise I don't want exercise.hpp to be included in the compilation command. I also tried to use the following instead.
CXXFLAGS=-Wall -std=gnu++17
create-exercise.o: create-exercise.cpp exercise.hpp
That generated g++ -Wall -std=gnu++17 -c -o create-exercise.o create-exercise.cpp. I don't want the -c flag. because when I try to run create-exercise.o that results in permission denied error. I tried the following as well:
CXXFLAGS=-Wall -std=gnu++17
create-exercise.o: create-exercise.cpp exercise.hpp
$(CXX) $(CXXFLAGS) create-exercise.cpp -o create-exercise.o
but when I edit exercise.hpp make says 'create-exercise.o' is up to date. and doesn't recompile it. what should I do?
The rule to write in your makefile would be:
create-exercise.o: exercise.hpp
This is a rule without a recipe, and it simply adds one more prerequisite (exercise.hpp) to the target create-exercise.o, i.e., whenever exercise.hpp changes, create-exercise.o should be rebuilt.
However, the problem when providing that rule is that GNU Make assumes create-exercise.o is an object file generated from a C source file when building create-exercise. Therefore, it doesn't link the C++ library but the C library instead, that's why you are having the liking error of undefined reference to std::cout.
GNU Make has the following implicit rule for generating an executable from a C++ source file:
%: %.cpp
# commands to execute (built-in):
$(LINK.cpp) $^ $(LOADLIBES) $(LDLIBS) -o $#
You can use that rule's recipe to build create-exercise from creating-exercise.o and still treat creating-exercise.o as an object file that was generated from a C++ source file:
create-exercise: create-exercise.o
$(LINK.cpp) $^ $(LOADLIBES) $(LDLIBS) -o $#
The whole makefile would be then:
CXXFLAGS = -Wall -std=gnu++17
create-exercise: create-exercise.o
$(LINK.cpp) $^ $(LOADLIBES) $(LDLIBS) -o $#
create-exercise.o: exercise.hpp
The target create-exercise also becomes the default goal because it's the first rule in the makefile. It's the target to build if you don't specify any to make.
You can do this:
CXXFLAGS = -Wall -std=gnu++17
create-exercise: create-exercise.o
$(LINK.cpp) $^ $(LDLIBS) -o $#
create-exercise.o: exercise.hpp
This says: build create-exercise from the object file create-exercise.o, if it's changed. And it says rebuild create-exercise.o if the header file exercise.hpp changes; it's not right to modify or rebuild a source file if a header changes. It's the object file that depends on the header.
Make has a number of built in rules. Among them are rules that know how to link a program but unfortunately that assumes your object files were built from C files, so if you're using C++ you have to create a specific recipe. But you can still use GNU make's default variables.
It also knows how to build a .o file from a .cpp file on its own: you don't need to write that recipe.
I am not sure, but maybe try to include the .hpp file instead of compiling it with the other file. You can do so by using g++ *.cpp -I *.hpp -o output
Try it out and let me know if it works for you.
I'm trying to write a makefile for all of my cpp prjects. After searching from the internet, I make a makefile as below:
g++11=g++ -std=c++11 -stdlib=libc++
CPPFILES=$(wildcard *.cpp)
OBJFILES=$(CPPFILES:.cpp=.o)
res.out: $(OBJFILES)
$(g++11) -lncurses -o $# $^ -g
#obj/%.o: %.cpp
%.o: %.cpp
$(g++11) -c -o $# $< -g
clean:
rm *.o *.out
I tried to use this file to compile my cpp projects and it worked well.
However, when I make some change in the header files, it doesn't work anymore because this makefile can't detect the modification in header files.
Is there any easy way to specify header files in the makefile?
Ofc I don't want to specify them one by one.
First of all, you should understand the concept of make.
Make is not only for compiling C++, it's a universal tool where a product (file) is built from other files. When you issue the make, it checks whether the top product should be rebuilt, based on the file change dates of dependencies. If rebuild is needed, first checks all the dependencies whether they should be rebuild... and so on. These bricks are called rules.
This is a rule:
target: dependency1 dependency2 ...
command1 to produce targets
command2
In case of a CPP project:
myapp: myapp.cpp myapp.hpp
g++ myapp.cpp -o myapp
More info: http://www.cs.cmu.edu/~gkesden/412-18/fall01/projects/proj1/make/makeintro.html
Edit: whoops. Forgot to put the correct link while formatting
I'm following this tutorial, but I have gotten an error I can't fixed (I've looked at my code and then back at his for around 25 minutes. I'm sure it's not a typo anywhere)
C:\Users\badfitz66\Rastering>make
g++ makefile.cpp -o makefile
g++: error: CreateProcess: No such file or directory
make: *** [makefile] Error 1
The code of makefile.cpp is:
OBJ = main.o
INC = -I "./"
Rastering: $(OBJ)
g++ $(OBJ) -o Rastering.exe
rm -f $(OBJ)
main.o:
g++ -c main.cpp $(INC)
clean:
rm -f $(OBJ) Rastering
When you write -o makefile it means you want your C++ compiler to write its output to a file named makefile. Since Windows has case-insensitive file systems, that is a very bad idea because you will end up overwriting your Makefile, which should be named Makefile.
Also, you seem very confused about the difference between a Makefile and a C++ file. The file you posted is a Makefile, so it should be named Makefile, not makefile.cpp. You will need to have at least two files: Makefile, and main.cpp. If you want more help, you will have to show us the full contents of both of those files and the exact output you get when you run make.
The error g++: error: CreateProcess: No such file or directory is usually caused by your toolchain not being installed properly. You will need to install a C++ compiler that provides an executable named g++.exe and make sure that you add the directory with g++.exe in it to your PATH environment variable. The tutorial video you linked to ought to tell you how to do that.
I've tried to add the following lines to my makefile in order to add some MATLAB plots to my C++ routine, to set the environment variables:
export PATH='/APP/MATLAB/R2013a/bin':$PATH
export LD_LIBRARY_PATH='/APP/MATLAB/R2013a/bin/glnxa64:/APP/MATLAB/R2013a/sys/os/gnlxa64':$LD_LIBRARY_PATH
And to provide the code with the correct location for the include files at compilation time:
.cpp.o:
g++ -c -DUNIX $(DEBUG) -I $(NR_DIR):/APP/MATLAB/R2013a/extern/include/ $<
$(CMD): $(OBJ)
g++ -o $# $(OBJ) -L$(NR_DIR) -lnr -DUNIX -I $(NR_DIR):/APP/MATLAB/R2013a/extern/include/
Where I've only added :/APP/MATLAB/R2013a/extern/include/ to the includes.
The compilation runs normally, except that the one .cpp file I've made changes to (which is the one that requires the new includes) sends the following error:
which sounds like I should install g++ but how could that be if g++ is run for all the other files properly and it's also working just fine compiling the original program?
I would like to know if I am making a mistake in the compiler call and if the exports are not all right. This is working properly on my laptop but now that I've tried to migrate the program to our school's cluster it's become messy.
The -I option to g++ does not presume a semicolon-divided directories list. This means you have to use -I option for each directory. Example:
-I $(NR_DIR) -I/APP/MATLAB/R2013a/extern/include
I have:
main.cpp
distance.cpp
distance.h
adjacencyList.cpp
adjacencyList.h
Here is my makefile:
all: distance main adjacencyList
g++ distance.o main.o adjacencyList.o
main.o: main.cpp
g++ main.cpp -lstdc++
adjacencyList.o: adjacencyList.cpp
g++ adjacencyList.cpp -lstdc++
distance.o: distance.cpp
g++ distance.cpp -lstdc++
clean:
rm -rf *.o all
I am getting this error. So I'm pretty sure I'm doing something wrong with main because it is not a class like the other two and does not have a .h file.
Update:
After trying Ben Voigt's solution I am getting 1 error:
Your rules to create object files are missing the -c option, for "compile only". So they are trying to link, and failing because there is no main().
Then, your all target names an executable for each of the compilation units. Again, that's wrong because they don't all have main(). You should have only one executable. all should also be configured as a phony target, because it doesn't build an actual file named all.
All your rules are failing to control the name of the output file.
All your rules are failing to pass flags.
Your rules are missing dependencies on the headers, so editing headers won't cause the right files to be recompiled.
Really, you should get rid of the compile and link rules and let make use its built-in ones. Focus on your build targets and dependencies.
Your end makefile should look something like this (of course, using spaces not tabs)
all : main
.PHONY : all clean
CC = g++
LD = g++
main : main.o adjacencyList.o distance.o
main.o: main.cpp adjacencyList.h distance.h
adjacencyList.o: adjacencyList.cpp adjacencyList.h
distance.o: distance.cpp distance.h
clean:
rm -rf *.o main
Wild guess: it is possible you are missing a semi-colon somewhere before including adjacencyList.h.
Check each header files and make sure each class definition is properly terminated with a semi-colon