I am taking a C++ course in college and they want us to manually type in all of the test files... I know, however, that there is a way to do it with out, which is how I ended up with the current(http://pastebin.com/6d9UtKM4) makefile. My question is, why is this makefile automatically removing all the .o files it uses for compiling when it is done? It's not killing me, but I would like to preserve the .o files. I have pasted the makefile here(http://pastebin.com/6d9UtKM4). I have also pasted the current result of running "make tests" here(http://pastebin.com/h3Ny3dib). (Note the part at the bottom of that page that removes all the .o files automatically.)
I would also like to be able to make it generate it like this:
g++ -o compileDir/assembler.o -c -Wall src/assembler.cpp
g++ -o compileDir/string.o -c -Wall src/string.cpp
g++ -c -Wall -o compileDir/test_assignment.o testSrc/test_assignment.cpp
g++ -o testDir/test_assignment compileDir/test_assignment.o compileDir/string.o compileDir/assembler.o
g++ -c -Wall -o compileDir/test_bracket.o testSrc/test_bracket.cpp
g++ -o testDir/test_bracket compileDir/test_bracket.o compileDir/string.o compileDir/assembler.o
testDir/test_bracket
testDir/test_assignment
In other words, I want it to compile everything, then run everything. I hope this isn't too much to ask!
Edit: Additional Information: (This is the code that does "make tests")
tests: assembler.o string.o $(test_output) $(test_stringOutput)
#echo '--- Testing complete ---'
$(testDir)%: $(compileDir)%.o string.o
g++ -o $# $< $(compileDir)string.o $(compileDir)assembler.o
$#
#echo ''
$(compileDir)%.o: $(testSourceDir)%.cpp
g++ -c -Wall -o $# $<
$(compileDir)%.o: $(testStringSrc)%.cpp
g++ -c -Wall -o $# $<
EDIT: -----------------------------------------
Resolved via comments:
Adding this line fixed it:
.PRECIOUS $(compileDir)%.o
You might add
.PRECIOUS: %.o
which should be implicit, but perhaps you've got a weird setup.
Make treats your .o files as intermediate and removes them. You can prevent automatic deletion of those by adding them a dependency of the special .SECONDARY target. See Chains of Implicit Rules for more details. Good luck!
Related
I'm attempting to create my first ever Makefile and looking for the most simple, understandable version--even if it isn't "good practice." I'll deal with that at a later time. :)
Basically, I just want to run make in the command line and have it execute the several g++ commands so I don't have to. For example, instead of entering the following (at top level dir) in the command line...
$g++ -c ./src/RaspPi4Main.cpp -o ./src/RaspPi4Main.o
$g++ -c ./src/funcI2cCom/funcI2cCom.cpp -o ./src/funcI2cCom/funcI2cCom.o
$g++ -o ./bin/RaspPi4Main ./src/RaspPi4Main.o ./src/funcI2cCom/funcI2cCom.o -lwiringPi
...I'd like something similar to my attempt at a Makefile:
RaspPi4Main: RaspPi4Main.o funcI2cCom.o (and all header files? or not needed if added below?)
g++ -o ./bin/RaspPi4Main ./src/RaspPi4Main.o ./src/funcI2cCom/funcI2cCom.o -lwiringPi
RaspPi4Main.o: RaspPi4Main.cpp
g++ -c ./src/RaspPi4Main.cpp -o ./src/RaspPi4Main.o
funcI2cCom.o: funcI2cCom.cpp funcI2cCom.h
g++ -c ./src/funcI2cCom/funcI2cCom.cpp -o ./src/funcI2cCom/funcI2cCom.o
Hopefully, I'm close? Thanks!
As a first step, you need to make sure your recipes produce their target and that inputs are either files or targets of other rules:
bin/RaspPi4Main: src/RaspPi4Main.o src/funcI2cCom/funcI2cCom.o
g++ -o bin/RaspPi4Main src/RaspPi4Main.o src/funcI2cCom/funcI2cCom.o -lwiringPi
src/RaspPi4Main.o: src/RaspPi4Main.cpp
g++ -c src/RaspPi4Main.cpp -o src/RaspPi4Main.o
src/funcI2cCom/funcI2cCom.o: src/funcI2cCom/funcI2cCom.cpp src/funcI2cCom/funcI2cCom.h
g++ -c src/funcI2cCom/funcI2cCom.cpp -o src/funcI2cCom/funcI2cCom.o
Note that this is quite verbose. You can shorten it quite significantly by making use of automatic variables. Concretely, $# is the name of the target, $< is the name of the first dependency, and $^ are all dependencies:
bin/RaspPi4Main: src/RaspPi4Main.o src/funcI2cCom/funcI2cCom.o
g++ -o $# $^ -lwiringPi
src/RaspPi4Main.o: src/RaspPi4Main.cpp
g++ -c $< -o $#
src/funcI2cCom/funcI2cCom.o: src/funcI2cCom/funcI2cCom.cpp src/funcI2cCom/funcI2cCom.h
g++ -c $< -o $#
Note that there's quite some repetition. Luckily, Make already knows how to compile a .cpp file into a .o file through implicit rules. Thus you can omit the recipes for these rules:
bin/RaspPi4Main: src/RaspPi4Main.o src/funcI2cCom/funcI2cCom.o
g++ -o $# $^ -lwiringPi
src/RaspPi4Main.o: src/RaspPi4Main.cpp
src/funcI2cCom/funcI2cCom.o: src/funcI2cCom/funcI2cCom.cpp src/funcI2cCom/funcI2cCom.h
I need help configuring my makefile to use it with the GNU debugger. I am running it on debian.
I am quite new to makefiles and after going through similar questions I've tried adapting the answers of those to my code, but it didn't work out the ways I tried (probably because i don't fully understand the syntax of makefiles).
This is the original (shortened) makefile:
INC=-I include
all: libs poisson_solver
poisson_solver:
g++ -o bin/poisson $(INC) src/main.c\ src/problem_setup.c\ libs/timer_tools.o
libs: libs/timer_tools.o src/problem_setup.o
libs/timer_tools.o: utilities/gettime.c
g++ -c -o libs/timer_tools.o $(INC) utilities/gettime.c
src/problem_setup.o: src/problem_setup.c include/problem_setup.h
g++ -c -o src/problem_setup.o $(INC) src/problem_setup.c include/problem_setup.h
Your Makefile has several errors, and in general contains more cruft than it should.
Here is roughly what it should be:
CFLAGS = -Iinclude -g
OBJS = src/main.o src/problem_setup.o utilities/gettime.o
all: poisson_solver
poisson_solver: $(OBJS)
src/problem_setup.o: src/problem_setup.c include/problem_setup.h
See this section of the manual.
I've been building a C++11 library, and the number of header/source files has grown to the point where compiling programs invoking it, entails passing 20+ .cpp files to g++. I've been reading up on shared libraries and it seems to be the best solution.
However, as headers/source change frequently, I'm hoping to create a makefile that would automatically generate all the .so files from the headers and source.
To better demonstrate what I'm trying to do, I'll take one of my sub-libraries, Chrono and show how I would do this manually.
I first create the object files like so,
$ g++ -std=c++11 -fPIC -g -c -Wall ../src/Chrono/cpp/DateTime.cpp
$ g++ -std=c++11 -fPIC -g -c -Wall ../src/Chrono/cpp/Schedule.cpp
$ g++ -std=c++11 -fPIC -g -c -Wall ../src/Chrono/cpp/Duration.cpp
$ g++ -std=c++11 -fPIC -g -c -Wall ../src/Chrono/cpp/DayCount.cpp
So that I now have DateTime.o, Schedule.o, Duration.o, and DayCount.o in the current directory. I then create the .so file,
$ g++ -shared -Wl,-soname,libChrono.so.1 -o libChrono.so.1.0.1 DateTime.o Schedule.o Duration.o DayCount.o -lc
I then go,
$ rm ./*.o && ldconfig -n ./
So that my working directory now contains, libChrono.so.1.0.1 and the symlink libChrono.so.1.
There are quite a few subdirectories I need to do this for, so you can see that this quickly grows inefficient whenever changes to headers/source are made. I would be grateful if anyone can help me design a makefile that accomplishes all this simply by invoking make.
Thanks!
UPDATE:
Based on goldilock's advice and some digging, I managed to bang together:
CXX=g++
CFLAGS=-std=c++11
TARGET=./lib/libChrono.so.1.0.1
CHRONODIR=./src/Chrono
CHRONOSRC=$(wildcard $(CHRONODIR)/cpp/*.cpp)
CHRONOOBJ=$(join $(addsuffix ../obj/, $(dir $(CHRONOSRC))), $(notdir (CHRONOSRC:.cpp=.o)))
all: $(TARGET)
#true
clean:
#-rm -f $(TARGET) $(CHRONOOBJ)
./lib/libChrono.so.1.0.1: $(CHRONOOBJ)
#echo "======================="
#echo "Creating library file $#"
#echo "======================="
#$(CXX) -shared -Wl,-soname,$(join $(basename $#), .1) -o $# $^ -l
#echo "-- $# file created --"
$(CHRONODIR)/cpp/../obj/%.o : $(CHRONOSRC)
#mkdir -p $(dir $#)
#echo "============="
#echo "Compiling $<"
#$(CXX) $(CFLAGS) -fPIC -g -Wall -c $< -o $#
4 .o files are produced in lib/ but I get multiple definition complaints from ld. Before I was compiling the object files separately, but this unwinds CHRONOOBJ on one line. Any ideas?
Fortunately you included the origin of your problem:
I've been building a C++11 library, and the number of header/source files has grown to the point where compiling programs invoking it, entails passing 20+ .cpp files to g++.
Because this reveals a potential XY problem. The straightforward solution to this is to put object files into an archive (aka. a static library) and use that.
GNU make has an implicit rule for creating C++ .o files. It amounts to this:
%.o: %.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $<
Meaning, if you make DateTime.o in a directory with a makefile that doesn't redefine this, it will make DateTime.o. You may want to add things to $(CXXFLAGS) however, e.g.:
CXXFLAGS += -Wall -Wextra --std=c++11
If you intend to stick with the shared lib route, -fPIC can go there too. That one line could be your entire makefile.
However, you also want to put these together, so you must first declare all the objects and a rule for combining them:
OBJS = DateTime.o Schedule.o Duration.o
libChrono.a: $(OBJS)
ar crvs $# $^
This last line (see man ar) creates the archive (libChrono.a) containing all the objects in $(OBJS). You can then use this with whatever program by placing it in the same directory (or a directory in the library path) and linking -lChrono. Only the necessary parts will be extracted and compiled in. This saves you having to maintain a shared lib in a system directory.
If you still think you need a shared lib, $# and $^ are automatic variables; you can use similar methodology to create a .so, something along the lines of:
SO_FLAGS = -shared
libChrono.so.1.0.1: $(OBJS)
$(CXX) $(SO_FLAGS) -Wl,-soname,libChrono.so.1 -o $# $^ -lc
If that is your first rule, make will take care of everything: building first the objects and then the library. Notice this one has excluded your normal $(CXXFLAGS) to duplicate exactly the compiler line from the question.
I have made a Makefile for my CMSC 202 course project, 'Blackjack'. It does everything I need it to and it works perfectly. You may be asking why I posted here then, this is because I have no idea how it works and I didn't use any other resources but myself to create it.
Here is my Makefile code.
# Object files to either reference or create
OBJECTS = Proj2.o Blackjack.o Deck.o Card.o Hand.o Player.o
# The executable file that will be created at the end
EXEC = Proj2.out
# The flags to use for compilation
FLAGS = -Wall
# The code compiler to use for compilation
CC = g++
# Perform action on all object files (May or may not exist)
all: $(OBJECTS)
$(CC) $(FLAGS) -o $(EXEC) $(OBJECTS)
Here is the terminal output when I call make in the terminal.
g++ -c -o Proj2.o Proj2.cpp
g++ -c -o Blackjack.o Blackjack.cpp
g++ -c -o Deck.o Deck.cpp
g++ -c -o Card.o Card.cpp
g++ -c -o Hand.o Hand.cpp
g++ -c -o Player.o Player.cpp
g++ -Wall -o Proj2.out Proj2.o Blackjack.o Deck.o Card.o Hand.o Player.o
Can anyone tell me how the .o files are being compiled? It does not look like they are being prompted to be compiled with that g++ -c -o $.o $.cpp command anywhere in the Makefile. Nor did I state to use any .cpp files.
Thank you in advance for your help.
Edit
Thanks to all your great help, this is now the terminal output I receive when using make.
g++ -Wall -c -o Proj2.o Proj2.cpp
g++ -Wall -c -o Blackjack.o Blackjack.cpp
g++ -Wall -c -o Deck.o Deck.cpp
g++ -Wall -c -o Card.o Card.cpp
g++ -Wall -c -o Hand.o Hand.cpp
g++ -Wall -c -o Player.o Player.cpp
g++ -Wall -o Proj2.out Proj2.o Blackjack.o Deck.o Card.o Hand.o Player.o
Thank you so much to all of you who have contributed.
Make has a set of implicit rules (see here for a reference). For instance
Compiling C++ programs
`n.o' is made automatically from `n.cc' or `n.C' with a command of the form
`$(CXX) -c $(CPPFLAGS) $(CXXFLAGS)'.
Most make's will also use this rule for .cpp files.
When make sees there's a x.o requirement for one of your targets, it will try to see if it can generate x.o using implicit rules, and in your case find it can do it starting from a .cpp file.
This Makefile uses implicit rules which are a great way to reduce duplication.
By default the first target will be built, here all. It depends on a number
of object files listed in a variable $OBJECTS, e.g. Proj2.o who's
dependencies aren't listed in the Makefile. Now if make sees an input file in the current directory
with a matching name, e.g. Proj2.cpp it will try
to build Proj2.o from it (there are other implicit rules for sources in
other languages). Proj2.o would then be built by default with the command
$(CXX) $(CXXFLAGS) -c -o Proj2.o
where $(CXX) the name of the C++ compiler (g++ in your case).
The explicit build step for all assembles all the object files into the
target executable.
Looking at above build command you'll notice a small problem in your Makefile. Since the flags to the C++ compiler are given in a variable FLAGS and not the standard CXXFLAGS no warnings will be emitted when building the object files. Using the standard name would fix this (you do want warnings, maybe even more than -Wall gives you).
I have a Makefile that works for how I'm using it, but will anyone tell me if what I'm doing is good practice? Or if there is a better, cleaner or more efficient way to achieve the goal I am reaching?
Here is my Makefile Code.
# Object files to either reference or create
OBJECTS = Proj2.o Blackjack.o Deck.o Card.o Hand.o Player.o
# The executable file that will be created
EXEC = Proj2.out
# The c++ flags to use for compilation
CXXFLAGS = -Wall
# The c++ compiler to use for compilation
CXX = g++
# This section is called on 'make'
# Will call compile, and then call clean
all: compile clean
# Perform action on all object files (May or may not exist)
# The makefile will implicitly compile all .o files needed
# Will also compile them into the EXEC file listed
compile: $(OBJECTS)
$(CXX) $(CXXFLAGS) -o $(EXEC) $(OBJECTS)
# This section is called after compilation is completed
# This will clean all existing .o files listed in the directory
clean:
rm -f *.o
Here is the terminal output when I call make.
g++ -Wall -c -o Proj2.o Proj2.cpp
g++ -Wall -c -o Blackjack.o Blackjack.cpp
g++ -Wall -c -o Deck.o Deck.cpp
g++ -Wall -c -o Card.o Card.cpp
g++ -Wall -c -o Hand.o Hand.cpp
g++ -Wall -c -o Player.o Player.cpp
g++ -Wall -o Proj2.out Proj2.o Blackjack.o Deck.o Card.o Hand.o Player.o
rm -f *.o
Is it good practice to use a Makefile like this? Specifically, am I doing the cleaning part of my Makefile correctly?
You should not make all depend on clean at all. By doing this you are ensuring that every time you run make, you have to recompile everything. If you want to do that then using make is itself useless: just write a shell script that compiles and links your code.
The clean target should be a separate target and if you want to clean your workspace you run make clean explicitly.
The other problem with your makefile is that the link rule lists compile as the target, but it builds $(EXE). It's almost never a good idea to have a rule create a file which is not exactly the target you told make it would build. To ensure this, always use $# as the target to generate. Rewrite it like this:
compile: $(EXE)
$(EXE): $(OBJECTS)
$(CXX) $(CXXFLAGS) -o $# $^