I have 3 files: node.h, node.c and main.c
If the Makefile is
CFLAGS += -std=c99 -g -Wall
run: node
./node
node: node.o main.o
Then, when I run make, these commands are run
cc -std=c99 -g -Wall -c -o node.o node.c
cc -std=c99 -g -Wall -c -o main.o main.c
cc node.o main.o -o node
./node
I guess the first two lines are generated because
First, maketry to run node but it cannot find node.
Thus, make holds run and goes to the next target, which is node at line 4.
Then, make sees the dependencies node.o and main.o. At this time, it knows that it must create object files node.o and main.o
However, I cannot understand why the third command is generated
cc node.o main.o -o node
In an attempt to explore this mystery, I observe that if node at line 2 is changed to node1, an error will occur
CFLAGS += -std=c99 -g -Wall
run: node1
./node1
node1: node.o main.o
From https://www.gnu.org/software/make/manual/html_node/Catalogue-of-Rules.html#Catalogue-of-Rules:
Linking a single object file
n is made automatically from n.o by running the linker (usually called ld) via the C compiler. The precise recipe used is ‘$(CC) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS)’.
This rule does the right thing for a simple program with only one source file. It will also do the right thing if there are multiple object files (presumably coming from various other source files), one of which has a name matching that of the executable file.
When you changed from node to node1, there is no longer a node1.c (therefore no implicit node1.o, and therefore the implicit rule does not apply).
Related
I am trying to compile a simple Antlr4 project. When I do it in single g++ command, it compiles successfully. However, when I compile and link separately, it fails.
Single stage compilation (succeeds):
g++ -std=c++11 -Wall -Wextra *.cpp -L. -l antlr4-runtime -I/usr/local/include/antlr4-runtime -. -o exec
Two stage (fails: cannot link properly to antlr library and gives a lot of undefined reference errors):
main: $(OBJS)
g++ -L. -l antlr4-runtime $^ -o exec
%.o: %.cpp
g++ -std=c++11 -Wall -Wextra -I/usr/local/include/antlr4-runtime -I. -c $<
I wonder why linking fails in the latter case, while it has similar linking options to single stage compiling.
I'm trying to create a makefile titled 'p1' for a project.
When I try the command make p1 it returns with make: nothing to be done for p1
Also, when I try the command make p1 clean it returns no rule to make p1 'clean.' Stop
Here is my makefile:
a.out: main.o P1LinkedList.o const_iterator.o iterator.o Node.o
g++ -std=c++11 main.o const_iterator.o iterator.o Node.o
main.o:
g++ -std=c++11 -c main.cpp
P1LinkedList.o:
g++ -std=c++11 -c P1LinkedList.cpp
iterator.o:
g++ -std=c++11 -c iterator.cpp
const_iterator.o:
g++ -std=c++11 -c const_iterator.cpp
Node.o:
g++ -std=c++11 -c Node.cpp
depend:
g++ -MM main.cpp > p1.dep
clean:
rm -f a.out *.o
What do I need to fix to have the makefile compile .o files from my .cpp files and how do I fix the issue with the clean command?
Edit:
Here are the commands I've used to compile manually:
Helens-Air:p1a helenade$ g++ -std=c++11 *.cpp
Helens-Air:p1a helenade$ ./a.out
^^ and this just continues with the program execution from there
We may have to take this in stages.
First, you seem to misunderstand the difference between a makefile name and a target name. This appears to have been a miscommunication between you and your teacher, but it's easy to clear up.
Suppose you have a makefile named "Makefile", containing the following:
foo:
#echo running the foo rule
bar:
#echo running the bar rule
If you make foo, you will get:
running the foo rule
The argument (foo) tells Make which target to attempt to build. And how did Make know which makefile to use? (After all, you could have a dozen makefiles in the working directory.) You can specify which makefile to use, but if you don't then by default Make will look for a makefile named Makefile (or makefile or GNUmakefile, don't worry about this for now). To specify a makefile with another name, like "Buildfile", you can use the -f flag:
make -f Buildfile
So "p1" ought to have been the name of a target, not a makefile. Within the makefile, rename your a.out rule to p1. Then rename the whole makefile to Makefile. Then
make p1
should work (or at least run).
Edit:
I'll go out on a limb. In the a.out rule (which should now be called the p1 rule), I notice that you have left P1LinkedList.o out of the list of object files to be linked. So try changing it:
p1: main.o P1LinkedList.o const_iterator.o iterator.o Node.o
g++ -std=c++11 main.o P1LinkedList.o const_iterator.o iterator.o Node.o
If that works, you can simplify it with an automatic variable:
p1: main.o P1LinkedList.o const_iterator.o iterator.o Node.o
g++ -std=c++11 $^
And there will be other small improvements you can make.
If it doesn't work, try ls *.cpp and see if you've overlooked some other source file.
I am writing my first MPI-based C program. I have four files namely, MPI_Program.c and Helper.c, and their corresponding .h files. MPI_Program.c includes mpi.h and Helper.h.
I wrote the following simple makefile to compile MPI_Program but I get the error "No rule to make target mpi.h"
Here's the makefile:
# Rules to produce the target
all: MPI_Program
MPI_Program: MPI_Program.o Helper.o
mpixlc MPI_Program.o Helper.o -f machineFile -std=c99 -g -o MPI_Program
# Rules to produce the object files
Helper.o: Helper.c Helper.h
gcc -c Helper.c -std=c99 -g
MPI_Program.o: MPI_Program.c MPI_Program.h Helper.h mpi.h
mpixlc -c MPI_Program.c -std=c99 -g -f machineFile
I am certainly missing something...Can someone please advise.
I want to build an app and I have multiple modules stored in multiple directories. I've decided to follow this idea, i.e. to have a makefile in each directory and then to merge it. But - as a beginner programmer - I still do not see how to do that. First of all, how would such "partial" makefiles look like. They cannot have main function as there can be only one per binary, though when I try to compile it gcc complains for the undefined reference to main. Secondly, I have no idea how would putting all those modules together look like.
I would appreciate any help, but please try to keep your answers simple. Makefiles are still a bit of black magic to me.
Before you can do anything with a makefile, you must know how to do it without a makefile.
Since you are using gcc, I will assume that your source code is C++.
You haven't told us what your directory structure looks like, so I'll suppose that you have three source files in two directories: primary/main.cc, other/foo.cc and other/bar.cc. (We can deal with header files like foo.h later.) And you want to build myApp.
STEP 1: Doing It By Hand
To do this in one command, you might use:
gcc -Wall primary/main.cc other/foo.cc other/bar.cc -o myApp
This will compile the three source files and link the binary objects together into the executable myApp.
STEP 2: Doing It In Pieces (Do not attempt this until you can get the previous step to work perfectly.)
Instead of building with one command, you could take an intermediate step, compiling the source files into binary object files:
gcc -Wall -c primary/main.cc -o primary/main.o
gcc -Wall -c other/foo.cc -o other/foo.o
gcc -Wall -c other/bar.cc -o other/bar.o
This will produce alpha/main.o, beta/foo.o and beta/bar.o. The compiler won't complain about foo and bar lacking a main() function, because an object file doesn't need one. Then link the objects together into an executable:
gcc -Wall primary/main.o other/foo.o other/bar.o -o myApp
STEP 3: Doing It Locally (Do not attempt this until you can get the previous step to work perfectly.)
Just like the previous step, but we act in primary/ and other/:
cd primary
gcc -Wall -c main.cc -o main.o
cd ../other
gcc -Wall -c foo.cc -o foo.o
gcc -Wall -c bar.cc -o bar.o
cd ..
gcc -Wall primary/main.o other/foo.o other/bar.o -o myApp
STEP 4: Using a Makefile (Do not attempt this until you can get the previous step to work perfectly.)
We could have a makefile perform STEP 1, but that isn't really necessary. Write a makefile in primary (i.e. primary/makefile) like this:
main.o:
gcc -Wall -c main.cc -o main.o
(That whitespace in fromt of gcc... is a TAB.)
Now try this:
cd primary
make
cd ../other
gcc -Wall -c foo.cc -o foo.o
gcc -Wall -c bar.cc -o bar.o
cd ..
gcc -Wall primary/main.o other/foo.o other/bar.o -o myApp
STEP 5: Using Several Makefiles (Do not attempt this until you can get the previous step to work perfectly.)
Write a other/makefile:
both: foo.o bar.o
foo.o:
gcc -Wall -c foo.cc -o foo.o
bar.o:
gcc -Wall -c bar.cc -o bar.o
and a makefile in the top directory, where you're building myApp:
myApp:
gcc -Wall primary/main.o other/foo.o other/bar.o -o myApp
Now try this:
cd primary
make
cd ../other
make
cd ..
make
STEP 6: Using One Makefile That Calls Others (Do not attempt this until you can get the previous step to work perfectly.)
Edit the top makefile:
myApp:
cd primary; make
cd other; make
gcc -Wall primary/main.o other/foo.o other/bar.o -o myApp
Now try:
make
If all of this works, what you have is a crude but effective makefile system. There are many refinements possible, when you're ready to take the training wheels off.
EDIT:
If there are many source files in a subdirectory (e.g. other/) and you don't want to maintain a list in the top makefile by hand, there are several ways to handle it. This is one:
OTHER_SOURCES := $(wildcard other/*.cc)
OTHER_OBJECTS := $(OTHER_SOURCES:.cc=.o)
myApp:
cd primary; make
cd other; make
gcc -Wall primary/main.o $(OTHER_OBJECTS) -o myApp
But you should get these makefiles working and understand them, before you try any more streamlining.
I have two files without main
X.h
X.cpp
I want compile these in one makefile
My makefile is ;
CXX = g++
CXXFLAGS_W = -Werror -Wunused-variable -Wunused-value -Wunused-function \
-Wfloat-equal -Wall
CXXFLAGS_M = -ansi -pedantic-errors
CXXFLAGS = ${CXXFLAGS_M} ${CXFLAGS_W}
all: main
./main
When I use like make X , compiler gives some error "undefined reference to main ". Due to that reason, I want new makefile. X can be any name .
You would generally have something like:
X.o: X.cpp X.h
g++ -c -o X.o X.cpp # or $(CXX) $(CXXFLAGS) -c -o ...
with whatever other flags you needed. -c tells the compiler to just compile rather than compile and link, and you don't usually compile the header file directly, rather you #include it in the cpp file.
Here's a makefile which combines two separate source files into a single executable:
xy: x.o y.o
g++ -o xy x.o y.o
x.o: x.cpp x.hpp y.hpp
g++ -c -o x.o x.cpp
y.o: y.cpp y.hpp
g++ -c -o y.o y.cpp
The x.cpp file includes x.hpp and y.hpp while y.cpp only includes y.hpp. The final executable is xy.
The first rule builds the executable from the two object files. The second and third rules builds the two object files, which is what I think you're asking for in the question.