Makefile not processing all commands - makefile

I am trying to convert a hello.c to hello stepwise by first preprocessing then compiling, then assembling then linking. However only the first command of my makefile is being executed:
Osheens-MacBook-Air-1115:Assignment0.1 osheensachdev$ ls
hello.c makefile
Osheens-MacBook-Air-1115:Assignment0.1 osheensachdev$ cat makefile
hello.i : hello.c
gcc -E hello.c -o hello.i
hello.s : hello.i
gcc -S hello.i -o hello.s
hello.o : hello.s
gcc -c hello.s -o hello.o
hello : hello.o
$ld hello.o -e main hello
clean:
rm hello.i hello.s hello.o hello
Osheens-MacBook-Air-1115:Assignment0.1 osheensachdev$ make
gcc -E hello.c -o hello.i
Osheens-MacBook-Air-1115:Assignment0.1 osheensachdev$ make
make: `hello.i' is up to date.
I've searched online about chained files and didn't find anything specific about why this shouldn't work.
I've also specified the target: [dependancies] so I don't see why this shouldn't work.

The first target of a Makefile is the default target.
This is why you see in many Makefiles a all target at the top which is intended to "make everything":
all: build test
build: <prerequisites>
test: <prerequisites>
Since you didn't specify one, Make builds hello.i only (plus everything needed to build this target):
hello.i doesn't exist yet.
hello.i needs hello.c. Make hello.c first.
hello.c is "made" already. Nothing to do.
Now make hello.i i.e., run gcc -E hello.c -o hello.i.
Stop
Then you ran Make again (without any specific target)
hello.i exists already. Nothing to do.
Stop.
I suspect that you wanted to make "hello", i.e., your program.
Either:
Move "hello" at the top and make it your default target
Or run make hello

Related

How to make multiple targets by the same rule using target-dependent compilers?

Suppose that I would like to verify the compatibility of hello.c with multiple compilers. How to do it using a Makefile?
Here is a Makefile I write for this purpose.
# Makefile, version 1.
# It tests hello.c using multiple compilers.
TEST = test_gcc test_clang
.PHONY: $(TEST) all
all: $(TEST)
test_gcc: CC = gcc
test_clang: CC = clang
$(TEST): hello
./hello
rm -f hello
hello: hello.c
$(CC) hello.c -o hello
If I run make test_gcc or test_clang, everything works. However, make all leads to the following.
./hello
Hello, world!
rm -f hello
touch hello.c
./hello
makeĀ : ./hello : command not found
make: *** [Makefile:10 : test_clang] Error 127
So hello is not remade for test_clang. This seems to a Makfile beginner like me.
Question: In my Makefile, test_clang depends on hello, which has been removed when test_gcc is finished. So why doesn't make generate it again before running ./hello ?
My Attempts:
To solve the problem, I tried the following modification, which touches hello.c after making test_gcc or test_clang. It still does not work, the problem being the same.
# Makefile, version 2.
# It tests hello.c using multiple compilers.
TEST = test_gcc test_clang
.PHONY: $(TEST) all
all: $(TEST)
test_gcc: CC = gcc
test_clang: CC = clang
$(TEST): hello hello.c
./hello
rm -f hello
touch hello.c
hello: hello.c
$(CC) hello.c -o hello
Following the advice of #HolyBlackCat, I tried also the following.
# Makefile, version 3.
# It tests hello.c using multiple compilers.
TEST = test_gcc test_clang
.PHONY: $(TEST) all
all: $(TEST)
test_gcc: CC = gcc
test_clang: CC = clang
$(TEST): hello_$(CC)
./hello_$(CC)
rm -f hello_$(CC)
hello_$(CC): hello.c
$(CC) hello.c -o hello_$(CC)
The output of make all is
gcc hello.c -o hello_gcc
./hello_gcc
Hello, world!
rm -f hello_gcc
./hello_clang
makeĀ : ./hello_clang : commande not found
make: *** [Makefile:13 : test_clang] Error 127
This is even stranger --- hello_clang is never made even though it is required (only) by test_clang.
For your convenience, here is the standard hello.c I used for the test.
/* hello.c */
#include <stdio.h>
int main()
{
printf("Hello, world!\n");
return 0;
}
Thank you very much for any suggestions. It will also be appreciated if you comment on my Makefiles in general, not necessarily regarding the question I raised. I am really a beginner.
See the documentation for target-specific variables: it's quite clear that target-specific variables take effect only in recipes. You cannot use them in prerequisites, or of course when defining targets.
It's probably simpler to do this without target-specific variables and just use pattern rules instead:
TEST = test_gcc test_clang
.PHONY: all
all: $(TEST)
test_%: hello_%
./$<
hello_%: hello.c
$* $< -o $#
(I don't know why you're removing the binary immediately after you test it, in this version, so I removed that).

Why does make insist that the files are up to date

Consider this simple example of a Makefile on FreeBSD.
all: hello
hello: hello.o
gcc -o hello hello.o
hello.o: hello.c
gcc -c hello.c
clean:
rm hello.o hello
And whatever I do, change hello.c, or even if I change the content in the Makefile to complete nonsense, make says:
`makefile' is up to date.
What could be an explanation whats going on there?
I guess you have small mess with makefiles. Please note that (for GNU Make): By default, when make looks for the makefile, it tries the following names, in order: GNUmakefile, makefile and Makefile. - make sure you haven't created GNUmakefile`
When it comes to FreeBSD based make it will be: If no -f makefile makefile option is given, make will try to open 'makefile' then 'Makefile' in order to find the specifications.
The only case, I can imagine, follows:
> cat Makefile
all: hello
hello: hello.o
cc -o hello hello.o
hello.o: hello.c
cc -c hello.c
clean:
rm hello.o hello
> make
cc -c hello.c
cc -o hello hello.o
> ./hello
Hello world!
> make clean
rm hello.o hello
> touch makefile
> echo "makefile:" > .depend
> make
`makefile' is up to date.

makefile erro " *** No target specified and no makefile found.stop."

I have a makefile that contains this code
all: hello.exe
hello.exe: hello.o
gcc -o hello.exe hello.o
hello.o: hello.c
gcc -c hello.c
clean:
rm hello.o hello.exe
When i write this command
mingh32-make
I got this:
mingw32-make : *** No targets specified and no makefile found. Stop.
You can solve this in 2 ways.
As the commenters say, rename your file from makefile.txt to makefile.
Another way, use mingw32-make -f makefile.txt

Trying to Figure out Makefiles

So, I am brand new to makefiles, and I am horrible on the command prompt. So I want to make sure my syntax is correct.
I have three files:
main.cpp
Blob.cpp
Blob.h
I would create a file (in notepad or something) called makefile.make and in it the text would read:
all:
g++ main.cpp Blob.cpp Blob.h -o hello
I then run in command prompt
make
and the file will be created? Is this correct? They are all in the same directory, along with some other folders that VS2012 put in there.
If you just want to rebuild the executable when every any file has changed, use
all: hello
hello: main.cpp Blob.cpp Blob.h
g++ -o hello main.cpp Blob.cpp
If you want separate compilation you do
all: hello
hello: main.o Blob.o
g++ -o hello main.o Blob.o
main.o: main.cpp Blob.h
g++ -o main.o main.cpp
Blob.o: Blob.cpp Blob.h
g++ -o Blob.o Blob.cpp
In both cases we tell make what file are dependencies (that is, if those files change we need to rebuild) in addition to specifying the work to be done.
try this
hello:main.cpp Blob.cpp
[TAB] g++ main.cpp Blob.cpp -o hello
Name it as Makefile or makefile. You can run just make to build it. Else name it anything you like, ex mymakefile and run make -f mymakefile to build it
Get fresh with basic makefile rules
Google "makefile tutorial" and you'll find plenty of sites.
The commands to run have to be preceded by a Tab character, so it should be:
all:
g++ main.cpp Blob.cpp -o hello
Make sure you're not using an editor that converts Tab characters to spaces.

Makefiles in multiple directories

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.

Resources