Make: Unexpected Behavior with Dependencies and include Statement - include

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.

Related

'make: nothing to be done for p1 and' no rule to make target 'clean''

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.

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.

How to generate multiple executable files in one Makefile?

My directory contains 2 source files: a.c and b.c. I want to generate executable file a from a.c and b from b.c. Now I can only figure out one method to write Makefile:
all:
gcc -o a a.c
gcc -o b b.c
It seems a little awkward, is it better method?
The answers are fine, still I think you need some insight in how make works:
The basic functionality of make is to create output files from input files if necessary. make decides what is necessary by comparing timestamps: If any input file is newer than an output file created from it, the recipe for this output file is executed.
This means with just a rule named all, this rule is always executed (except when you happen to have a recent file actually called all -- to prevent this behavior, you have to list all as a .PHONY target, that is one that doesn't actually create a file). Your original Makefile is equivalent to a simple shell script, so it doesn't use make properly.
The minimal "correct" version of your Makefile should look like this:
all: a b
a: a.c
gcc -o a a.c
b: b.c
gcc -o b b.c
.PHONY: all
So, all is "phony" and depends on a and b. a is only rebuilt when a.c changed, b is only rebuilt when b.c changed.
In a real project, your programs are probably made from more than just one source file and in this case, you can really take advantage of make: Have it build object files of your translation units, so only the parts that changed are actually rebuilt. It's overkill for your tiny example, but could e.g. look like this:
a_OBJS:= a.o
b_OBJS:= b.o
all: a b
a: $(a_OBJS)
gcc -o$# $^
b: $(b_OBJS)
gcc -o$# $^
%.o: %.c
gcc -c -o$# $<
clean:
rm -f *.o
.PHONY: all clean
You would just have to add more object files to a_OBJS and b_OBJS to include new translation units in your build. The pattern rule %.o: %.c will match them. There's a lot more to discover, I suggest starting with the GNU make manual.
I think the follow method is better:
all: a b
a: a.c
gcc -o a a.c
b: b.c
gcc -o b b.c
In your version, make all will always run gcc twice, whether or not a.c and b.c are modified. In this version gcc will be run only when necessary.
Of course you can use some magic (for-loop or similar) to create the rules but I think the difference between my and your method is clear.
To me
all:
gcc -o a a.c
gcc -o b b.c
looks fine.
Or may be the following for better control
all: a b
a: a.c
gcc -o a a.c
b: b.c
gcc -o b b.c
clean:
-rm a b
A lesser known trick to compile without makefile
make a #run cc -o a a.c by make or
make b #run cc -o b b.c by make
Or to generate both a and b
make a b
make uses implicit rule here, just like magic. But prefer a makefile with rule specified

make is calling g++ is always re-compiles even when I do not change the source code

I am using make which calls g++ always re-compiles the code, even when I do not change the source code. That happens for all my projects, even for simple ones such as:
[code]
all: main.cpp
g++ -std=c++11 -c main.cpp
[/code]
I believe it should compare the date/time on source and object code. Could some help me with this, I am running using GNU toolchain on Ubuntu 12.04
THX
Edit: sorry guys, I do use Makefile, I edited my question accordingly.
Simplest Makefile
It was already pointed out that your Makefile is probably wrong. The 'all' target is indeed always built (although it may result in a no-op if it has no commands and all dependencies are already satisfied). All you need in your makefile is this:
all: main
Object files
If you expect to have more source file in your build, you should consider creating intermediate object files:
all: main
main: main.o
Tweak the build
Make will automatically find the main.ccp file and turn it into main which is required per the directive above. You can use special make variables to further tweak the compilation, e.g. for debug information inclusion and for warning configuration:
CXXFLAGS = -g -Wall -Werror
all: main
main: main.o
Nitpicking
If you insist on building up the compile rule yourself, you can do it like this:
%.o: %.hpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $# -c $<
CXX: C++ compiler
CPPFLAGS: C preprocessor flags
CXXFLAGS: C++ compiler flags
$#: Target
$<: First dependency
If you don't want to use the standard variables nor pattern matching, you can build up the whole makefile explicitly:
all: main
main: main.o
gcc -o $# $^
main.o: main.c
gcc -g -Wall -Werror -o $# -c $<
$^: Use that one if you want to include all dependencies, for example if you have multiple *.o files to build one binary.
Note: It is a bad idea to write the file names directly into the command as you might forget to update them later.
all: main.cpp
g++ -std=c++11 -c main.cpp
This seems wrong. Why does the rule for all has main.cpp as its target? Shouldn't it be something.exe or something.o? Say
all: main.exe
main.exe: main.cpp
g++ -std=c++11 main.cpp -o main.exe
clean:
del main.exe
Targets are output files and cpp files are source code which should be input to the make system.
g++ would have to "recompile" in general (what happens if you change the header but not main.cpp?)
If you are concerned about long build times, you should use something like Make (which is designed specifically to avoid recompiling when the source hasn't changed)
The compiler will always compile the code. If you want to do conditional compilation (based on file times etc) you will need to use a make system such as Make, CMake, Ant, etc. For the simplest you can set up a small "Makefile" in the directory and use the command "make" to build.
Simple Makefile for compiling "myapp.exe" from "main.cpp", "file1.cpp" and "file2.cpp"
myapp.exe: main.o file1.o file2.o
g++ -o myapp.exe main.o file1.o file2.o
(make knows to use .cpp files to build .o files)
But if you also have header files, then you will need to build dependency chains, for which you may want to look into something more sophisticated like automake, cmake, ant, etc.
---- EDIT ----
Based on your updated post, the problem is that you aren't specifying a target, so Make has to assume it needs to recompile. See my example in the above answer.

makefile compile multiple source files in one call

Imagine that I have 2 source files that both include one header file.
a.c:
#include "ab.h"
int a() {
return RETURN_VAL;
}
b.c:
#include "ab.h"
int b() {
return !RETURN_VAL;
}
ab.h:
#define RETURN_VAL (0)
I want a makefile that can compile in one call a.c and b.c. If ab.h is new or a.c and b.c are both new, then I want:
gcc -c a.c b.c
touch ab.timestamp
Otherwise I want to recompile only the out of date files.
This is a tiny example, I need something that scales. I have attempted to resolve this, but I can't figure out how.
This is an example using C, but my actual use is for compiling large-scale HDL projects. As the invocation of the HDL compilers has a high overhead, it is much better to call the tool once for many files instead of separately for each.
What I have tried are things like:
a.c: ab.h ;
b.c: ab.h ;
ab.timestamp: a.c b.c
gcc -c $?
touch ab.timestamp
This won't work, and instead I need something like this:
ab.timestamp: a.c b.c ab.h
gcc -c a.c b.c
touch ab.timestamp
This is what I don't want. I would like $? to indicate the correct files that I need to recompile. I know that I can use $(if and $(filter functions to figure this out, but I was hoping for something more seamless.
I am using GNU Make.
Thanks,
Nachum
This is a trick, but it might work:
all: ab.timestamp
SOURCES = a.c b.c ab.h
a.o: a.c ab.h
b.o: b.c ab.h
CHANGED :=
%.o: %.c ; $(eval CHANGED += $<)
ab.timestamp: $(SOURCES) $(patsubst %.c,%.o,$(filter %.c,$(SOURCES)))
gcc -c $(CHANGED)
touch $#
This is a kludge, but it seems to work. Touch the source files to bring them up to date with the header:
a.c b.c: ab.h
#touch $#
ab.timestamp: a.c b.c
gcc -c $?
touch ab.timestamp

Resources