Why does make insist that the files are up to date - makefile

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.

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).

Makefile not processing all commands

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

Why doesn't this Makefile work?

I have this C file:
// test.c
#include <stdio.h>
int main()
{
printf("Hello World!\n");
return 0;
}
And this Makefile
OBJS=$(patsubst %.c,%.o,$(wildcard *.c))
EXEC=hello.exe
all: $(EXEC)
$(EXEC): $(OBJS)
.PHONY: all
When I do make it doesn't create my target hello.exe why?
$ make
cc -c -o hello.o hello.c
It doesn't either work with hello.exe:
$ make hello.exe
make: Nothing to be done for 'hello.exe'.
And hello.exe doesn't exist:
$ ls hello.exe
ls: cannot access 'hello.exe': No such file or directory
I use this version of GNU Make
$ make --version
GNU Make 4.2.1
Built for x86_64-unknown-cygwin
Copyright (C) 1988-2016 Free Software Foundation, Inc.
EDIT
It actually works when I name my executable the same of any of my files. So it works with:
EXEC=hello
See:
$ make
cc -c -o hello.o hello.c
cc hello.o -o hello
That said I don't understand why it only works that way.
The version with hello.exe does not work because make has no implicit rule to tell it how to turn a bunch of *.o into a single *.exe.
But it does have implicit rules (at least those specified by POSIX) to turn hello.c into hello.o and link into hello.
Remember, Unix is not DOS. Forget the .exe when you're on Unix.

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

Why automatic variable in my makefile doesn't find any target?

I've written this hello world in hello.c:
#include <stdio.h>
int main() {
printf("Hello, World!\n");
exit( 0 );
}
my Makefile is:
%: %.c
When I run make I will get this error: make: *** No targets. Stop.
Your makefile provides a rule %: %.c specifying that it's extensionless executables and .c files that you're interested in (in fact, just the built-in rules do that much), but gives no hint that there's a source file named hello.c or a target named hello.
When you type make by itself, make takes the first target listed in the makefile as the target to be made, but your makefile contains no targets whatsoever, hence No targets. Stop. In short, make has no clue that there is anything nearby with a name like hello*.
With your makefile as is, typing make hello will do what you want, as it tells make what it is that you'd like to build.
If you tell make about hello, you'll also be able to type just make to do what you want:
hello: hello.c
%: %.c
or more idiomatically and flexibly, you would list all your "top-level" targets in an all target:
all: hello
%: %.c
.PHONY: all
Typical c hello world prgram:
hello.c:
#include <stdio.h>
int main() {
printf("Hello, World!\n");
return 0;
}
Typical Makefile, short but complete:
Makefile:
all: hello
hello: hello.o
gcc -o "$#" hello.o
hello.o: hello.c
g++ -c hello.c
.PHONY:clean
clean:
rm *.o hello
Example with pattern rules:
all: hello
hello: hello.o
gcc -o "$#" hello.o
%.o: %.c
gcc -c $<
.PHONY:clean
clean:
rm *.o hello
Example with delimiter(\n as enter, \t as tab):
all: hello\n
hello: hello.o\n
\tgcc -o "$#" hello.o
%.o: %.c\n
\tgcc -c $<
.PHONY:clean
clean:\n
\trm *.o hello

Resources