Here's my problem : I have a makefile file containing the info to compile everything in my project to make my life easier, but it is giving me some headaches recently.
It can compile multiple files, such as this :
objects/io.o: sources/io.cpp
#g++ -c $< -o $# -std=c++11
objects/map.o: sources/map.cpp
#g++ -c $< -o $# -std=c++11
At the top of the makefile, I have variables declared as such :
IO="objects/io.o"
MAP="objects/map.o"
[... other object files ...]
ALL="$(IO) $(MAP) [...]"
When I want to compile my main file, I use this command :
main.exe: tests/main.cpp
#g++ $< $(ALL) -o $# -std=c++11
When I compile this problem manually (inputting everything in one line of command, instead of making make main.exe) it compiles without problems.
However, when I use the make command for the project, the following error pops up :
clang: error: no such file or directory: 'objects/io.o objects/map.o [...]'
make: *** [main.exe] Error 1
Can I not use variables this way ? I'm extremely confused. I know for a fact those files are compiled, it just seems the make utility doesn't understand file paths.
I think the problem is that you have quoted your variables. Try unquoting them and they won't expand a single parameter:
ALL = $(obj1) $(obj2) ...
Also, for those objects which use the same compilation process I generally define a single rule:
obj/%.o: %.cc
$(GCC) -o $# -c $< $(FLAGS)
Obviously that would require defining the extra variables GCC and FLAGS
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.
C++ newbie here my command is g++ main.cpp -o main gives me linking errors like the following
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
if i pass c++ files g++ main.cpp myfile.cpp -o main everything is correct
any ideas how to compile multiple c++ files without passing everything in command line.
Thanks
any ideas how to compile multiple c++ files without passing everything in command line.
To build an application you need all object files, so you have to pass all cpp files to compiler.
But for simple cases when all cpp-files stay at single folder, you can
use command (simple, but slow method):
g++ *.cpp -o main
any ideas how to compile multiple c++ files without passing everything in command line.
First create object files:
g++ -c main.cpp -o main.o
g++ -c myfile.cpp -o myfile.o
Then pass them to the linker:
g++ main.o myfile.o -o main
Though there is a fairly large learning curve for Make, a make file is the preferred solution. On SO, I have also noticed significant use of CMake.
Additional ideas for your Makefile:
The following two rules handle 90% of my simpler unit test executables:
R01 handles files with both .cc and .hh
R02 handles files with only .cc
# pattern rule R01
# when any ARCHIVE changes, trigger a rebuild
% : %.cc %.hh $(LIB_ARCHIVEs)
#echo
#echo R01: $<
rm -f $#
$(CC) $(CC_FLAGS) $< -o $# $(LIB_DIRs) $(LIB_NMs)
# pattern rule R02
# when any ARCHIVE changes, trigger a rebuild
% : %.cc $(LIB_ARCHIVEs)
#echo
#echo R02: $<
rm -f $#
$(CC) $(CC_FLAGS) $< -o $# $(LIB_DIRs) $(LIB_NMs)
Occasionally, I will add specific LIB names and directories ... directly to the LIB_DIRs and LIB_NMs definition in the Makefile. For example, here I have added -lrt and -pthread:
LIB_NMs += -lbag_i686 -lposix_i686 -lrt -pthread
bag_i686 and posix_i686 are libraries I built ... simple C++ class wrappers around the linux and posix functions. Most of my unit tests do not use much of posix stuff, but I get no grief including it.
With C++ std::thread, I seldom use -pthread. However, I occasionally use posix semaphore.
My compile command line access (in emacs on Ubuntu) provides a history, so the occasional change or addition to the command line is only a 'bother' one time. From then on, the newer command is available in history.
The emacs I launch is configured with an 'embedded' pre-defined compile command:
USER_FLAGS='-O0 ' ; export USER_FLAGS ; time make CC='g++ -m64' -j 2 -k
This command shows up the 1st time I launch the compiler from within emacs. Emacs presents it as if the command is already in 'compile-command history'.
I manually shorten this if I'm not rebuilding all, usually I only build a single ut:
USER_FLAGS='-O0 ' ; export USER_FLAGS ; time make CC='g++ -m64'
So, for example, when I am ready to compile dumy431.cc, I invoke:
USER_FLAGS='-O0 ' ; export USER_FLAGS ; time make CC='g++ -m64' dumy431
The next build I launch (from within emacs compile) starts with the previous command, and up/down arrow roll through any other versions of the command.
With this form of the command, I can trivially change from g++ to clang++ by inserting "clan" at the appropriate place:
USER_FLAGS='-O0 ' ; export USER_FLAGS ; time make CC='clang++ -m64'
clang++ often provides additional diagnostics that g++ does not report. To roll back to g++, I can up-arrow in the compiler command panel (or edit the command).
Here is a small example where my unit test code has multiple src files. Often, the non-main files (such as eng_format.*) are code that I plan to capture to one of my libraries for future use:
FMssb.o : FMssb.cc FMssb.hh
#echo
#echo R_FMssb.o: $<
rm -f $#
$(CC) $(CC_FLAGS) -c $< -o $#
FMssb_ut : FMssb_ut.cc eng_format.o FMssb.o $(LIB_ARCHIVEs)
#echo
#echo R_FMssb_ut: $<
rm -f $#
$(CC) $(CC_FLAGS) $< -o $# eng_format.o FMssb.o $(LIB_DIRs) $(LIB_NMs)
eng_format.o : eng_format.cpp eng_format.hpp $(LIB_ARCHIVEs)
#echo
#echo R_EF: $<
rm -f $#
$(CC) $(CC_FLAGS) -c $< -o $# $(LIB_DIRs) $(LIB_NMs)
I'm new to makefiles, and they puzzle me. I have the following folder hierarchy:
A folder named lib contains tow folders: include (with file mylib.h) and src (with file mylib.cpp). It also contains a Makefile, which, for some reason, gives me an error.
The full makefile is:
CFLAGS = -Wall -fPIC
OBJECTS = mylib.o
all: libmine.so
libmine.so: $(OBJECTS)
g++ -shared $(CFLAGS) \
-o libmine.so \
$(OBJECTS)
%.o: src/%.cpp include/%.h
g++ $(CFLAGS) \
-I include \
-o %.o \
-c src/%.cpp
clean:
rm src/*.o
rm libmine.so
The error is
mr209#Quantum:~/Desktop/hw1/lib$ make
g++ -Wall -fPIC \
-I include \
-o %.o \
-c src/%.cpp
g++: error: src/%.cpp: No such file or directory
g++: fatal error: no input files
compilation terminated.
make: *** [mylib.o] Error 4
But the file is present. Thus, make is doing weird things, causing it not to be able to find the .cpp file.
In order to make libmine.so, g++ will have to do something with mylib.o, and for a generic .o file I have written some lines of code.
Here is what I was thinking: in order to make libmine.so, g++ will have to do something with mylib.o. Thus, in lib, a file named mylib.o has to appear. Using the generic %.0 rule, this file is made from mylib.cpp in src and mylib.h in include (hence the first line of the %.o rule). The file is made using g++, which has to look in include for additional headers, produces mylib.o as output, and compiles src/mylib.cpp, but -c guarantees that a .o file is produced.
Obviously, something goes wrong, and I am unable to figure out what. Only 2 days ago have I learned what Makefiles are and why one should learn how to deal with them, so I'm not that much of an expert.
Your build target %.o is miswritten. You can't use the % in the command section, so the names of the destination file and dependent file won't ever match.
The proper change is to do the following:
%.o: src/%.cpp include/%.h
g++ $(CFLAGS) \
-I include \
-o $# \
-c src/$(#:%.o=%.cpp)
Just to explain the changes, the -o needs the target file, which is pretty much always written as $# in Makefiles, as that's the name of the target.
Secondly, the source file needs to be defined in terms of the target, the operator in question is a pattern replacement operator $(#:%.o=%.cpp), so what that does is take the target - which will match a filename of <blah>.o, then it pattern match replaces .o with .cpp.
So in the case of the target mylib.o, the variable $# is mylib.o, and the result of doing $(#:%.o=%.cpp) is to turn mylib.o into mylib.cpp. As a result it is the expected file that is being compiled, and the expected target is build.
Rules using a % pattern in them are what are referred to as implicit rules, and are used to reduce the complexity of the code being written - if you had a pile of files that shared the target pattern: blah.o: src/blah.cpp src/blah.h, then you use the implicit rule to only have to write the target once, then you need to write the commands in terms of the target.
You must do a variable before put it in g++
like :
FT_C= $(src/%.cpp)
FT_O=$(FT_C:.c=.o)
and
g++ $(CFLAGS) -I include -o $(FT_O) -c $(FT_C)
and don't put your .h in compilation '-I' are here for it.
Look this example if you want understand what i mean:
https://github.com/emericspiroux/wolf3d/blob/master/libft/Makefile
I'm trying to build a small C++ project with GNU make (version 3.81) but i must call make two times because the first run fails. This is my project directory:
project
makefile
include
lexer.hpp
src
main.cpp
lexer.l
Following is my makefile:
CC = g++
CPPFLAGS = -I include
VPATH = include src
OBJECTS = main.o lexer.o
test: $(OBJECTS)
$(CC) $(CPPFLAGS) -lfl -o $# $^
main.o: lexer.hpp main.cpp
$(CC) -c $(CPPFLAGS) $^
lexer.o: lexer.cpp
$(CC) -c $(CPPFLAGS) $^
lexer.cpp: lexer.l
flex -t $^ > src/lexer.cpp
.PHONY: clean
clean:
rm -fR $(OBJECTS) src/lexer.cpp test
The first time i run make i get the following output where make complains about not finding the lexer.cpp file. But i don't understand why make don't seek in the folders declared in VPATH.
g++ -c -I include include/lexer.hpp src/main.cpp
flex -t src/lexer.l > src/lexer.cpp
g++ -c -I include lexer.cpp
g++: error: lexer.cpp: No such file or directory
g++: fatal error: no input files
compilation terminated.
make: *** [lexer.o] Error 1
However if i call make again then lexer.cpp is found and the compilation works.
g++ -c -I include src/lexer.cpp
g++ -I include -lfl -o test main.o lexer.o
Why?
P.S. I apologize for poor english.
This rule is wrong:
lexer.cpp: lexer.l
flex -t $^ > src/lexer.cpp
This rule tells make that it will build a file lexer.cpp, and so that's what make is expecting it to do, and after the rule finishes make thinks that file is ready to go, and it will use that filename when other targets depend on it. But what the rule really does, is build src/lexer.cpp.
To write this rule correctly you'll need to write it as:
src/lexer.cpp: lexer.l
flex -t $^ > $#
(every make rule you write should always update the file $#, exactly).
However, in general VPATH is not good for finding generated files (object files, etc.: any file that is generated by make). It's only useful for finding source files (files make doesn't build itself).
This is my first, attempt at a, Makefile after necessity from a previous post.
Anyway here's the code
SortLab.exe : SelectionSort.o Main.o
g++ -o $# $^
SelectionSort.o : SelectionSort.cpp SelectionSort.h
Main.o : Main.cpp
#-------------------------------------------------------------
run: SortLab.exe
./SortLab.exe
clean:
rm -f *.o
rm -f *.exe
build: clean SortLab.exe
%.o: %.cpp
g++ -c $<
I intend to have SelectionSort.cpp & SelectionSort.h form an object file, and Main.cpp to form its own object file. Then finally create an executable. Main.cpp depends on SelectionSort.cpp, where do I go wrong?
Also where can I find what the different GNU commands mean, -o -c and such
You shouldn't need to define the %.o: %.cpp rule yourself, Make knows how to compile C++.
Indent with tabs, not spaces; Make is sensitive to the difference.
Every object file should depend on the headers included in the source files it depends on. You probably need Main.o : Main.cpp SelectionSort.h.
build shouldn't depend on clean, it defeats one of Make's main features (selectively recompilation when files have changed).
If you make build the first target, you can run Make without a target to get a full compile. It's customary to call the main target all.