Reputation:
Let's say, compiling hello.c requires car.c and water.c. But main.c requires hello.c.
When I say requires, I mean that the compiled output would differ if the things it requires is modified in any way.
So, if car.c or water.c is changed, then hello.c would need recompiling.
Then, would this be the correct Makefile?
main: main hello.o
gcc main.c hello.c -o main
hello.o: water.c, car.c
gcc water.c car.c -o hello.o
Otherwise, if it's not correct, can someone explain to me why it is wrong and give me an example?
Thank you!
Upvotes: 1
Views: 415
Reputation: 3073
What you're doing is a little strange, but I guess not incorrect. Don't have a recursive dependency on main and compile hello.o as an object file.
main: main.c hello.o gcc main.c hello.o -o main hello.o: hello.c water.c car.c gcc hello.c water.c car.c -c hello.o
Upvotes: 1
Reputation: 126233
Let's say, compiling hello.c requires car.c and water.c. But main.c requires hello.c.
This statement doesn't make a lot of sense. The only thing it could mean is that either these aren't C or C++ source files, rather some other language that uses these names confusingly, or they contain #include
directives that include those other files.
In that latter case (which is rare, and a poor design), there's no need to specify the included files on the command line, since gcc will include them for you. You just need to specify the dependencies in the Makefile:
main: main.c hello.c car.c water.c
gcc -o main main.c
since main.c
has #include "hello.c"
and hello.c
has #include "car.c"
and #include "water.c"
, only the one compile gets everything.
If these are some other language, and you mean something completely different, its likely that gcc
can't understand (or compile) them at all...
Upvotes: 3
Reputation: 5305
In your makefile there are entities of the following type:
main
main
executable). I can see hello.o
, but I cannot find water.o
, car.o
and main.o
(since each *.c
compilation unit is generally converted by the compiler to a *.o
compiled object).main.c
, hello.c
, water.c
and car.c
. These are used as inputs by the compiler to generate the corresponding *.o
files.So, based on the above, the appropriate Makefile would look like this (tested):
main.o:
gcc -c main.c
hello.o:
gcc -c hello.c
water.o:
gcc -c water.c
car.o:
gcc -c car.c
main: hello.o water.o car.o main.o
gcc hello.o water.o car.o main.o -o main
The shortened versioned, using makefile text functions and automatic variables (tested):
%.o:
gcc -c $(addsuffix .c, $(basename $@))
main: hello.o water.o car.o main.o
gcc $^ -o main
Another approach (tested):
SRC := hello.c water.c car.c main.c
OBJ := $(addsuffix .o, $(basename $(SRC)))
main: $(OBJ)
gcc $^ -o main
Upvotes: 0
Reputation: 58657
I would re-write it as:
SRC := hello.c main.c water.c
OBJS := $(patsubt %.c,%.o,$(SRC))
main: $(OBJS)
$(CC) -o $@ $^
This makefile works because there is an implicit rule for compiling C files. This will mean that when $(OBJS) is expanded to hello.o, main.o, and water.o, each of those .o files will be built by "$(CC) -o hello.o -c hello.c".
Note that if you use the GCC -c flag to only compile the file, but not link it, you will not need to be worried that hello.c relies on car.c and water.c.
EDIT:
Note that in your original makefile, the line "main: main hello.o" is incorrect. A target cannot depend on itself.
In general, with Make, you want to specify dependencies, but not the implementation of making those dependencies, if you can help it. It is much cleaner to say "I need this" versus "do these steps". In a lot of cases, Make is smart enough that if you say "I need this," it will "do the right thing."
Upvotes: 0