Where does 'All' belong in a Makefile? - c

Where do we put the all in a Makefiles?
I had a similar question found earlier, but I needed a little bit more details. I also looked at the GNU make manual, but got lost in the mountain of documentation. I tried the googles, but didn't find a good example. So, I did what was my last resort and tried to figure it out by hacking at a Makefile myself. I have:
CC=gcc
CFLAGS=-Wall -g
clean:
rm -f all: ex1
This didn't compile my ex1 in C. Also, if I wanted to add more to this make file. Like ex1, ex2, to exercise whatever. Would I just put the all at the top and repeat the
rm - f whatever
line below clean?
Appreciate your help and assistance. Patience appreciated too.

all is actually nothing special, just a target name commonly used. To make it work best, it should be the first target in the file. This makes it the default target, and gmake works the same as gmake all.
Normally, the all target has dependencies, which are the things which need to be built. E.g.
all: myexe
rm is related to the clean target (which is also nothing special, just a name commonly used). You define it this way:
clean:
rm -f myexe
This makes it delete myexe when gmake clean is run. If you makefile builds other files, they should also be listed there.
There's a lot more to know about makefiles. Normally you would use variables and template rules, which help you avoid repeating yourself. But this is far more than a simple answer can describe.

Related

How exactly "make all" works?

So I am studying makefiles usage. Let's say I 've many functions fun_i.c where i is in [1,100]. I have wrote them all in seperate .c files in order to make faster compilation when I only change some of them. I need to create a Makefile. I was thinking something like that:
all : program
program: fun1.o fun2.o ........ fun100.o main.o
gcc -o program fun1.o fun2.o ..... fun100.o
fun1.o: fun1.c
gcc -c fun1.c
.
.
.
fun100.o: fun100.c
gcc -c fun100.c
main.o : main.c
gcc -c main.c
I 've read many articles online talking about how the target "all" makes sure that everytime I change something in a function and I call make it will update only what changes (so I'm going to avoid uneccessary recompilation).
However, I am not sure if I am using it right here. I checked my makefile ( with 2 functions though) and it worked fine. But I am not sure if that's the way to take advantage of all here.
I tried to remove it and just leave program and below.. there and it worked as fine.
What am I missing?
Could you may provide examples that all is critical?
I 've read many articles online talking about how the target "all" makes sure that everytime I change something in a function and I call make it will update only what changes
all does not mean anything. It's just a convention. You have to define the targets correctly to do what you want. If you want make all to recompile everything, you need to define it so that it does that.
so I'm going to avoid uneccessary recompilation
In practice, I'd say that this is a completely unnecessary concern, and it's a waste of time creating makefiles that does this. If you have a large project you should not create makefiles manually. You use a build system like cmake.
If the project is small and only contain a few files, then the compilation time is in general not an issue. For a small project, my goal with a makefile would be to not have to type the compiler flags all the time.
Here is a makefile that would work fine for most very small projects like school assignments:
CFLAGS=-Wall -Wextra -pedantic -std=c17 -fsanitize=address
LIBS=-lm -lpthread
program:
gcc $(CFLAGS) $(LIBS) *.c
clean:
rm -rf *.o *~
Your makefile is fine, both with and without all: program.
The word all has no special significance in makefiles, using is just a convention. In your makefile all has no recipe (i.e. no commands associated with it), so make all and make program are equivalent.
Note that if you don't specify a target when invoking Make (e.g. make as opposed to make program), the first target in the makefile is built.

make: *** No rule to make target `clean'. Stop

I was walking through this tutorial, where I had to create this make file:
CFLAGS=-wall -g
clean:
rm -f ex1
When I type this command:
$ make clean
I get the following error:
make: *** No rule to make target `clean'. Stop.
I made sure that I'm using TABS. Why am I getting this error? How can I solve it?
The issue here, as indicated by a few comments on the post is that you named your file make instead of the traditional Makefile (or alternate names GNUMakefile and makefile that GNU make supports).
See What Name to Give Your Makefile in the GNU make manual.
If you want to use an alternate name (like make) then you need to tell make to use that file with the -f flag (also mentioned in that section of the manual).
make -f make
The missing separator error is caused by incorrect indentation in the makefile. Spaces instead of tabs on recipe lines, etc.
I was under the impression that targets should not have whitespace in front of them.
Also, Make treats the first target as the default target (what we traditionally call 'all'), so if 'clean' is your only target, it will get treated as the default.
I'm guessing your indentation is borked. Make is very, very specific in how files should be indented.
Your file should look like this:
CFLAGS=-wall -g
clean:
rm -f ex1
Notice how clean is all the way left in the file (has no whitespace in front of it), and how there are two tabs (represented here by 8 spaces because I have no way of representing tabs on SO...)
basically, Make is an ancient program that has very, VERY particular rules as to how things are done. Be careful and follow the indent rules as closely as you possibly can.

How to make a makefile properly, Why is this makefile not correct

I am trying to understand how to make a make file in Linux, and some one suggested to me to use this:
target: mytalkc.c mytalkd.c
gcc mytalkc.c -o mytalkc
gcc mytalkd.c -o mytalkd
When executing the above code exactly using "make" in the terminal everything ran great and everything compiled and made a executable successfully. So I thought this was correct, and I went with this for my makefile.
After futher documentation I learned that the correct way to make a makefile was not what I had above....
My question is, why does "target:" work and why was make was able to complete everything with no errors. Also why is things like "all:" used in make files over "target:" ?
Thanks in advance and sorry if it seems obvious, but I am new to Linux programming.
Typically a makefile is structured into multiple target rules, which contain dependencies that may rely on other dependences and so on. The word "all" is suggestive of "all targets", which means any dependencies of the "all" target are built. Additionally, some implementations of make allow for phony targets, such as "all", that tell make not to look for a file with one of the suffixes in a predefined suffix list, such as "all.c" to build the binary (program) with the filename "all".
Your actual question regarding why "target" works pertains to the behavior of make. It automatically makes the first target in the makefile unless a specific target is given. In your case, "target" is the first target in your file, so "make" by itself will make it (often "all" is used instead, but it is just a name; you should use "all" to simply because it is common practice).
Here is an example of how your file might be reworked with multiple targets (see the documentation for your make utility to understand the syntax, such as "info make" or "man make"):
all: mytalkc mytalkd
mytalkc: mytalkc.c
gcc $< -o $#
mytalkd: mytalkd.c
gcc $< -o $#
There are a lot of other things to address outside the scope of this answer, including implicit suffix rules and compiling several individual parts of a program/library together to create the program (splitting makefile rules into program/library: object1.o object2.o main.o and then individual rules for e.g. object1.o: object1.c). However, those are the basics that you need to know for now.
For what i know if you compile using gcc mytalkc.c -o mytalkc you are just compiling the source file as an object, it means that the compilation went well, but the file is not executable still because you haven't done any liking.
Try with this:
all: mytalkc.o mytalkd.o
mytalkc.o: mytalkc.c
gcc mytalkc.c -c mytalkc.c
mytalkd.o: mytalkd.d
gcc mytalkc.c -c mytalkd.c
invoking make all

When writing a Makefile how is all: used in it

I am currently learning c through a few differant sources one being Learn C The Hard Way PDF and Cprogramming.com for extra credit it says to use all: in the Makefile. I'm currently using Kali Linux, vim for my editor and so far my Makefile looks like so.
CFLAGS=-Wall -g
clean: "this is on the next line with a Tab in--->"
rm -f ex1
I'm just trying to understand the syntax and were to put the all: and how to add to it. it says to add my next project ex3 to the all: and the clean in my Makefile if someone could explain this a little better I would be very appreciative as I don't want to jump ahead without understanding all the extra credit.
If you need a reference point as to were I am on the 3rd lesson of LearnCTheHardWay. I'm just starting out with C using Linux. Thank you for your time and any answers you may have.
all has no special meaning to make. Same goes for clean.
make will use the first target it sees unless you specify otherwise via the command line invocation.
Reading the documentation is absolutely recommended, especially considering the GNU make docs are pretty well written and work as part-tutorial-part-reference.
I would recommend that you just build your programs from the command line. This should be no problem until the build command becomes more than a couple of lines.
At that point you will be (1)frustrated enough and (2)knowledgeable enough about the compilation process (preprocessing, compiling, assembling, linking, stripping) to learn about makefiles.
You can browse online tutorials, browse the gnu make documentation and experiment in your makefiles.
From there on, you might want to learn about build systems, like autotools and Cmake, probably a couple of years in the future.
In make file the format is like this,
<tag>: <dependency1> <dependency2>....
$CC <dependency1> <dependency2>....
<dependency1>: <dependencya> <dependencyb>....
$CC -c <dependencya> <dependencyb>....
So basically for all: you have add dependecy as *.o files, for the *.o file the dependenc

make: Nothing to be done for `all'

I am going through an eg pgm to create a make file.
http://mrbook.org/tutorials/make/
My folder eg_make_creation contains the following files,
desktop:~/eg_make_creation$ ls
factorial.c functions.h hello hello.c main.c Makefile
Makefile
# I am a comment, and I want to say that the variable CC will be
# the compiler to use.
CC=gcc
# Hwy!, I am comment no.2. I want to say that CFLAGS will be the
#options I'll pass to the compiler
CFLAGS=-c -Wall
all:hello
hello:main.o factorial.o hello.o
$(CC) main.o factorial.o hello.o -o hello
main.o:main.c
$(CC) $(CFLAGS) main.c
factorial.o:factorial.c
$(CC) $(CFLAGS) factorial.c
hello.o:hello.c
$(CC) $(CFLAGS) hello.c
clean:
rm -rf *o hello
error:
desktop:~/eg_make_creation$ make all
make: Nothing to be done for `all'.
Please help me understand to compile this program.
Sometimes "Nothing to be done for all" error can be caused by spaces before command in makefile rule instead of tab. Please ensure that you use tabs instead of spaces inside of your rules.
all:
<\t>$(CC) $(CFLAGS) ...
instead of
all:
$(CC) $(CFLAGS) ...
Please see the GNU make manual for the rule syntax description: https://www.gnu.org/software/make/manual/make.html#Rule-Syntax
Remove the hello file from your folder and try again.
The all target depends on the hello target. The hello target first tries to find the corresponding file in the filesystem. If it finds it and it is up to date with the dependent files—there is nothing to do.
When you just give make, it makes the first rule in your makefile, i.e "all". You have specified that "all" depends on "hello", which depends on main.o, factorial.o and hello.o. So 'make' tries to see if those files are present.
If they are present, 'make' sees if their dependencies, e.g. main.o has a dependency main.c, have changed. If they have changed, make rebuilds them, else skips the rule. Similarly it recursively goes on building the files that have changed and finally runs the top most command, "all" in your case to give you a executable, 'hello' in your case.
If they are not present, make blindly builds everything under the rule.
Coming to your problem, it isn't an error but 'make' is saying that every dependency in your makefile is up to date and it doesn't need to make anything!
Make is behaving correctly. hello already exists and is not older than the .c files, and therefore there is no more work to be done. There are four scenarios in which make will need to (re)build:
If you modify one of your .c files, then it will be newer than hello, and then it will have to rebuild when you run make.
If you delete hello, then it will obviously have to rebuild it
You can force make to rebuild everything with the -B option. make -B all
make clean all will delete hello and require a rebuild. (I suggest you look at #Mat's comment about rm -f *.o hello
I think you missed a tab in 9th line.
The line following all:hello must be a blank tab. Make sure that you have a blank tab in 9th line. It will make the interpreter understand that you want to use default recipe for makefile.
That is not an error; the make command in unix works based on the timestamps. I.e let's say if you have made certain changes to factorial.cpp and compile using make then make shows
the information that only the cc -o factorial.cpp command is executed. Next time if you execute the same command i.e make without making any changes to any file with .cpp extension the compiler says that the output file is up to date. The compiler gives this information until we make certain changes to any file.cpp.
The advantage of the makefile is that it reduces the recompiling time by compiling the only files that are modified and by using the object (.o) files of the unmodified files directly.
Using the comment from Paul R, I found that
make clean
followed by
make
or
make all
fixed my problem.
I arrived at this peculiar, hard-to-debug error through a different route. My trouble ended up being that I was using a pattern rule in a build step when the target and the dependency were located in distinct directories. Something like this:
foo/apple.o: bar/apple.c $(FOODEPS)
%.o: %.c
$(CC) $< -o $#
I had several dependencies set up this way, and was trying to use one pattern recipe for them all. Clearly, a single substitution for "%" isn't going to work here. I made explicit rules for each dependency, and I found myself back among the puppies and unicorns!
foo/apple.o: bar/apple.c $(FOODEPS)
$(CC) $< -o $#
Hope this helps someone!
I was trying to install libuv on Ubuntu and i also got the error make: Nothing to be done for 'all'. As i see it, using make gives two ways to solve the problem, one for check and one for install. But i found a workaround
still use the sudo make check command - it helps to read all the error messages before deciding on further actions. Basically, i've introduced a regression that makes the update workaround inefficient. This error comes from make however, the workaround from install fixes this, just try to run sudo make install and see what happens.
The make command will be a local optimization at the expense of the overall result of check/install - c'est ma façon de parler.
I believe i have narrowed down the problem considerably: in the first case after check i have "FAIL: test/run-tests" and in the second after install i get "specify the full pathname of the library, or use the '-LLIBDIR'" This argument to check/install can be a list object to store information about completed installations.
So install reports partial success when nothing actually happened.
Try running the commands from root:
cd your_program
sh autogen.sh
./configure
make
make check
make install
And then he writes that the installation was successful:
Libraries have been installed in:
/usr/local/lib
In your case, I strongly feel the only and simple problem you had is that you only preprocessed your app. You did so by having the flag -c under CFLAGS.

Resources