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.
Related
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).
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.
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
I have the following Makefile:
a.d:
gcc -m32 -MM -o $# a.c
sed 's!a.o!$# a.o!' --in-place $#
a.o:
gcc -c -m32 -o $# a.c
all: a.d a.o
-include a.d
The contents of a.d are:
a.d a.o: a.c a.h
I'm having 2 problems. 1, after running "make all" if I run:
touch a.h
make a.d
I see this:
gcc -m32 -MM -o a.d a.c
sed 's!a.o!a.d a.o!' --in-place a.d
make: 'a.d' is up to date.
The a.d rule clearly ran, why do I see "make: 'a.d' is up to date."?
2, after running "make all" when I run this:
touch a.h
make a.o
I see this:
gcc -m32 -MM -o a.d a.c
sed 's!a.o!a.d a.o!' --in-place a.d
gcc -c -m32 -o a.o a.c
Why did it also run the a.d rule? There are no dependencies on it.
What I really don't understand is when I replace "-include a.d" with the contents of a.d in the make file, for example:
#-include a.d
a.d a.o: a.c a.h
I don't see either problem. Shouldn't the include statement make it as if the include file were included directly in the same make file?
This is what my a.h looks like:
#define FOO 0
And this is a.c:
#include <stdio.h>
#include "a.h"
void foo(void)
{
printf("foo %d", FOO);
}
I'm using Cygwin 64-bit. Here's my output from make -v:
$ make -v
GNU Make 4.1
Built for x86_64-unknown-cygwin
Copyright (C) 1988-2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Both your behaviors are explained by the fact that GNU make tries to rebuild included makefiles; see How Makefiles are Remade. So, in your first question the first output is from when make tries to rebuild the a.d file and the second output is from after make re-execs itself; it sees that the goal a.d is up to date.
In your second question, it runs the a.d rule because a.d depends on a.h and since you include a.d, make tries to rebuild it.
For your last question, the reason it doesn't happen if you embed the content directly is that you're not using include.
Other interesting things to read are: Generating Prerequisites Automatically and Advanced Auto-Dependency Generation. Also maybe Constructed Include Files for more background.
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