How exactly "make all" works? - c

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.

Related

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

multiple small programs in one code::blocks project

I am new to Code::Blocks. For my studies I am programming several small programms in C (just to try things out).
I tried to put them all in one project, because they belong to the same topic, but that doesn't work because each of them has a main function.
Any ideas how I can put those files together somehow, but not depending on each other?
Suppose your source files are called
prog1.c
prog2.c
mylib.c
mylib.h
where prog1.c and prog2.c each contain a main() function and mylib.c (with the corresponding header file mylib.h) contains some library functions that should be linked to each program. In your Code::Blocks project you need to create multiple targets now. From the menu choose 'File/New/Build target...' and name them 'prog1' and 'prog2'. Now add all of your source files to the project (in case you haven't done so already).
Now right-click on prog1.c and select "Properties..." from the context menu. In the dialog box choose the 'Build' tab and make sure that under "Belongs to target" only "prog1" is checked. Do the same with prog2.c and the target "prog2". For "mylib.c" make sure that both "prog1" and "prog2" are checked.
Now you can easily choose in the UI which build target to build and run. Note that if you add another target, say "prog3", then you have to go to the build properties of prog1.c and prog2.c again and uncheck "prog3".
A C program should contain only one main function.. Divide all your separate programs as Functions and put them in a single C program or you can even put it in multiple files and compile them..
You can use a switch case for calling different functions..
Remove the main function from all the programs and convert them into functions..
Call them where ever required.. This will help you..
let's say that your project contains 3 c files and each c file is a separate program and it contains its own main function:
program1.c
program2.c
program3.c
So you can write a Makefile (its name in your computer should be "Makfile"). It will build the program you want separately
This is how your makefile looks:
all: program1 program2 program3
%.o: %.c
$(CC) $(CFLAGS) -c -o $# $^
program1: program1.o
$(CC) $(LDFLAGS) -o $# $^
program2: program2.o
$(CC) $(LDFLAGS) -o $# $^
program3: program3.o
$(CC) $(LDFLAGS) -o $# $^
clean:
rm -f *.o program1 program2 program3
with the above Makefile you can build each program separetly
example
$ make program1
will build only program1
or you can buil all programs with
$make all
It seems to me as if you are starting to build some nice utility functions. So follow the advice offered by raghu-srikanth-reddyce and create separate functions for each little program. However I would add that it would be better to create yourself a simple C library to keep them all in which you can link to at any time. Most professional programmers keep such libraries.
A simple makefile will enable you to build a final binary that you can link to.
Good luck with your programming ;)
If you want to compile in one file, you dont need a Project File then.
Just make a New File, then write all the code in a single file. Also use Function and Procedure if you need it.
This is quite late but since I was once here with the same question, and I believe most students had/ have/ will have this same question, let me elaborate where you have been played at.
In Educational Courses and in Real World, a project is (in general) some problem you work on, find a solution, then make a report (+ documentation) on it.
In Programming IDE, a project is the problem's solution itself. Hence, while you may have multiple individual problems within one project in any Python IDE, Any standard C/C++ IDE project must have only one 'main()' to rule them all (unless you know how to create makefiles).
What the AP tried to do is to put several different problem's solutions fit within one solution's space - not a possible thing to do in Code::Blocks. Even if all the problems may share the same topic (say, Graph Theory), they are individual problem (Dijkstra vs Floyd) themselves.

compile .c with gcc

I'm trying to compile a program that have main.c and a lot of .c and .h files .
Is there any way to compile and link without passing all .c file in the gcc command
like
gcc main.c file.c file2.c -o main
Your shell can expand wildcards. So you can:
gcc *.c -o main
Of course, you'll have to make sure that you don't have any extra *.c files in the directory that you don't actually want compiled. A better option is to use a build system such as Make or SCons.
'make' is the tool for building C apps. Below is the hello world version.
$ cat main.c
#include <stdio.h>
int main (char *argv[], int argc) {
printf("Hello World\n");
return 0;
}
$ make main
cc main.c -o main
$ ./main
Hello World
Edited in deference to Shahbaz comment:
The original question was trying to simplify the command-line for gcc. The right direction for the programmer is to learn about make. Since there is a bit of a learning curve with make, I wanted to offer simple stepping stone which does something useful. By getting started in this way, you don't need a make file. Simply type 'make programname' as shown above. Make uses its default rules and associated varabiles. $(CC) -c $(CFLAGS) $(CPPFLAGS) The astute programmer can build on this by setting well-know variables.
From here one can tinker with a makefile. In the spirit of stepping stones, consider this trival makefile
$ cat makefile
SRCS = main.c
OBJ = ${SRCS:.c=.o}
CC=gcc
main: ${OBJ}
$ make
gcc main.o -o main
By setting the well-known make variable CC to control which compiler is used. OBJ is computed from the list of source files. The trival target starts one on the road to rules.
Anyway, my hope is this post and other answers get the original questioner on there way.
Regards,
-jk
If you're asking about the command-line, you can just use wildcards to specify all the .c files as #Man of One Way suggested. But in general, C applications of any-but-trivial-size are built using "makefiles" which are extremely helpful.
You might want to read a tutorial such as http://www.cs.umd.edu/class/fall2002/cmsc214/Tutorial/makefile.html
gcc -o main -I. `find . -name "*\.c"`
This way you could have the .c and .h files in subfolders if you wish.
However, this is not a good way of doing it. A better way would be to create a Makefile
As already said, make is the best way to go
Learn just what you need at every point
Besides, it is important to also use some flags that will help you out while coding:
-Wall -> sets all warning flags
-g, -ggdb -> generates debug code
-ansi, -std=c99
A really good book on how to use make is,
http://shop.oreilly.com/product/9780937175903.do

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.

What is an efficient workflow with C? - Makefile + bash script

I'm working on one of my first projects that will span more than one C file. For my first couple practice programs, I just wrote my code in main.c and compiled using gcc main.c -o main. This worked for me as I was learning.
Now, I'm working on a much bigger project on my own. I want to continue doing compilation on my own (or at least setting it up manually) so I can understand the process. After reading a bit, I decided to make a Makefile.
Note: I'm also using GTK+, so I had to look up how to add that into the compile command.
This is what it looks like after a bit of research:
main:
gcc -Wall -g main.c -o main `pkg-config --cflags --libs gtk+-2.0`
At first, I was just running "make". Then I was having some problems getting the error "main is up to date" even though I had changed the file.
So I wrote a script:
#!/bin/bash
rm main
make
./main
So I make changes, and then I run this script.
Is this a good/normal system? I want to have scalable system, since my project will grow. I assume I can keep that script and just add dependencies to the makefile and change the main compile command in the makefile. Am I correct?
Thanks in advance.
EDIT:
Thanks for the feedback about how to fix my Makefile.
So is the typical compilation process 1) type make then 2) ./main regardless of how the project is setup or its size (assuming you've written a proper makefile)?
You need to tell make that main depends on main.c. That way every time you make changes to main.c and then run make, main is regenerated. To delete main you can have a phony target called clean as:
main:main.c
gcc -Wall -g main.c -o main `pkg-config --cflags --libs gtk+-2.0`
.PHONY: clean
clean:
rm -f main
Now to delete main you can do : make clean
If you get make: main is up to date. It means you've not modified main.c and hence there is not need for regenerating main. But if you have to force regenerating main even when the dependencies have not been updated you can also use the -B option of make as suggested by Sjoerd in other answer.
Use make -B or make --always-make to compile even though the target is up to date
Append filenames after the colon to check whether these are updated.
Example:
a: a.c
gcc -o a a.c
a would only be built if a.c is newer than a.
I find command-line make to be quite sufficient for my needs, but writing Makefiles by hand becomes quite a chore. As your project grows in complexity, you'll find managing the dependencies by hand to become more and more annoying. What I suggest you do is learn how to do at least one of the following:
Write a dependency-tracking Makefile by calling e.g., gcc -M.
Learn to use a Makefile generator such as automake or CMake. I personally prefer automake because it is more mature (and doesn't do stupid things like try to put semicolon-separated lists on a command line).

Resources