What is the difference between makefile and sh file - c

What is the difference between makefile and sh file. sh(shell
script file) file also can work at the place of makefile(means we can
do same thing using shell file like makefile can do) then what is
difference between them. there is any execution difference or any
standard where we have to use makefile and sh file.
one Example of this to compile a hello.c file with Makefile and shell file
shell.sh
param="$1";
CC="gcc"
CFLAGS="-c -Wall";
if [ "$param" == "clean" ];
then
rm -rf hello
else
$CC $CFLAGS hello.c -o hello
fi
./shell.sh { will build hello.c file }
./shell.sh clean { this will clean the build file }
Same thing with Makefile..
CC=gcc
CFLAGS=-c -Wall
hello: hello.c
$(CC) $(CFLAGS) hello.c -o hello
clean:
rm -rf hello
make {it will build}
make clean {it will clean build file}
Both files can generate same output.
This question because some people use Makefile and some people use shell..

make automatically checks (based on time stamps) which targets need to be remade and which ones can be left untouched. If you write your own shell script, you'll either have to program this logic yourself or else all your components will be rebuilt when you run your script - even those that haven't changed since the last build.

Related

How to compile and run a infinite loop .c program in a Makefile

System: VirtualBox Ubuntu 20.04
This question sounds like stupid, but I have stuck at this problem for hours. (Purely new to Makefile)
Here is the description:
The program (sh.c)simulates a shell, which is a infinite loop. User can exit if they enter builtin command exit, like below:
> gcc -o sh sh.c
> ./sh
>>> $ (user can enter command)
...
...
>>> $ exit
Goodbye!
> (back to bash)
The question is if I want to place gcc -o sh sh.c and ./sh into Makefile and enter make to run, bash will stuck like this:
> make
gcc sh.c -o sh
./sh
(stucking...)
and I cannot type commands also cannot exit by Ctrl + C.
I believe the problem is in the Makefile, because program can run smoothly if I don't use Makefile, and below is my Makefile:
all: compile run
.PHONY: all clean
CC := gcc
FLAG := -Wall
SRC := sh.c
EXE := sh
compile: $(SRC)
$(CC) -o $(EXE) $(SRC)
run:
./$(EXE)
clean:
rm -rf $(EXE)
I wonder what is the problem in the Makefile, thanks in advance!
The reason for this weird behavior must be related to your implementation of sh.c. Using a normal shell, for example, works fine for me:
$ cat Makefile
run: ; /bin/sh
Now I can run make and it starts a shell and I can type stuff into it and it works:
$ make
/bin/sh
$ echo hi
hi
$ exit
But, as John says, make is not intended to allow you to run interactive programs. It's intended to allow you to build programs and run other commands non-interactively. If you use make -j for example (parallel builds) only one rule can get access to stdin at a time and there's no way to know which one it will be. Etc.
You should keep the compile rule (although it should be written differently: it's always wrong for a make recipe to build a different file than the name of the target) but throw away the run rule, and just run the command from your shell prompt after make is done.
all: $(EXE)
$(EXE): $(SRC)
$(CC) -o $(EXE) $(SRC)

Script to create a static library from all .c file in my working directory

I am trying to write a script that create a static library call libwork.a in the working directory from all the .c files in the directory:
#!/bin/bash
gcc -c *.c | ar cr libwork.a *.o
But as I run my script, it only creates the object files. The libwork.a does not get created. I tried both sourcing and executing my script but it still only creates object files only.
Why is it not creating the archive?
You are piping the messages printed by gcc (most surely none) to ar (which does not read anything). This is nonesense, ar should run after gcc.
The file listing generated by "*.o" is passed before "gcc" finished.
The solution is to remove that pipe and simply run the commands one after the other.
#!/bin/sh -e
gcc -c *.c
ar cr libwork.a *.o
Note the "-e". This tells the shell to abort if one of the commands fails, so if gcc fails ar will not execute.
Also, have a look at this one:
#!/bin/bash
gcc -Wall -pedantic -Werror -Wextra -c *.c
ar -rc libwork.a *.o
ranlib libwork.a

How to create a makefile in gcc

I am trying to create a makefile but facing some issues.
I installed gcc compiler in Windows 7, then created one simple helloworld example. After that compiled that C file using the following command:
gcc filename.c
After this I am getting an exe file. I am calling this project in some tool for that, tool required makefie.
As I understood makefile is a text file, which tells or consist some commands how to build, run and clean the project.
So according to this I am writing a makefile:
CC=gcc
SRCS=src/hello.c
.PHONY: all
all: clean build
#echo ========== Complete ==========
.PHONY: build
build:
#echo ========== Build ==========
$(CC) hello.c
.PHONY: run
run:
#echo ========== Run ==========
make
.PHONY: clean
clean:
#echo ========== Clean ==========
rm hello.exe
./obj:
mkdir ./obj
While calling this simple project in tool, getting error
"no rule to make target clean"
Please tell me which steps I followed those are correct for creation of makefile or not, and what mistake I am doing? How to create a makefile?
In my opinion you have not got the essence of make(1):
Make stores in the makefiles a set of dependency rules (dependencies between files) in your build directory in order to build your project.
There are dependency lines, and build lines, the dependencies start in column 0 of the line, while the buid lines start with a tab char.
the rule lines have two parts, the file that is to be built, a colon (:), and the list of files it depends on (so that if one or more of these files is modified, the rule is applied)
If the rule has to be applied, then the set of build lines below the rule (until the next rule or a variable definition rule if found) is executed in order to build the file.
Example
Your file hello.c will be compiled into hello.s to create an assembler file, and then the assembly code is assembled to generate an object code hello.o. Finally, this file is linked to generate the file hello (or hello.exe, if you are in windows).
You arrange your makefile to generate all the files, in a way that if you modify e.g. the assembler file hello.s, only the assembler pass, and the linker pass is done, but not the compiling phase that should overwrite the assembler file before assembling. This can be done with this Makefile:
# this is the linking phase. The first rule in the file is the
# default target rule, so by default, executing make will try this
# rule (but only if hello.exe was modified before hello.o)
hello.exe: hello.o
gcc -o hello.exe hello.o
# Now, the assembling phase. The hello.o file depends on the
# hello.s assembly code, so to assemble it we call the assembler
hello.o: hello.s
as -o hello.o hello.s
# now, we specify the dependency from the hello.s assembler file
# from the hello.c source code file.
hello.s: hello.c
gcc -c -S -o hello.s hello.c
Now, if it is the first time you execute make and you have only the file hello.c (and Makefile of course) the make program will generate the following sequence of commands:
$ make
gcc -c -S -o hello.s hello.c
as -o hello.o hello.s
gcc -o hello.exe hello.o
$ _
but if you later modify the file hello.s (I will touch(1) it, to change its modification date:
$ touch hello.s
$ make
as -o hello.o hello.s
gcc -o hello.exe hello.o
$ _
but if you touch hello.c, everything will be made again:
$ touch hello.c
$ make
gcc -c -S -o hello.s hello.c
as -o hello.o hello.s
gcc -o hello.exe hello.o
$ _
Make builds a dependency graph and follows it in order to build the target you have specified in the command line, so if you use make with a target, it will stop as soon as the target is built:
$ make hello.o
gcc -c -S -o hello.s hello.c
as -o hello.o hello.s
$ _
I recommend you to read a book on make. A good one is the GNU Make documentation that is online on your system as an info file: just execute:
$ info make
(and info will open a text screen to allow you to read the full documentation of make)

How to properly create and use makefile

I'm getting started with makefiles and I'm having some problems.
I have one file which is fase_1.c that I want to compile and run.
I'm trying to make a simple makefile where I make and make clean.
This is what I tried:
OBJECTS = fase_1.o
CFLAGS = -Wall
NAME = makefile
build: $(OBJECTS)
cc $(CFLAGS) $(OBJECTS) -o $(NAME)
clean:
rm -f *.o
rm -f $(NAME)
I do make, and it creates fase_1.o and makefile. Then I run ./makefile (is there another way to do it without like make or make clean but to run it?). Then I type make clean, and it says that there's a missing separator and that the line is ignored and doesn't remove fase_1.o and makefile (what I want to do). Am I separating the lines right? Maybe it has something to do with tab or my editing but I can't find where.
Here's a rewrite. Call it Makefile, though, not makefile:
OBJECTS = fase_1.o
CFLAGS = -Wall
NAME = fase
$(NAME): $(OBJECTS)
cc $(CFLAGS) $(OBJECTS) -o $(NAME)
run : $(NAME)
./fase
.PHONY: clean
clean:
rm -f *.o
rm -f $(NAME)
There are fancier improvements that could be made, but it's probably best not to get bogged down at this stage. As a bonus, I have added .PHONY. This tells make that the target clean is a phony target; it doesn't actually create anything called clean.
You don't have to make run dependent on $(NAME), of course, but it makes sense in this particular context.
It looks like you are using GNU make. From the info page:
By default, when 'make' looks for the makefile, it tries the following
names, in order: 'GNUmakefile', 'makefile' and 'Makefile'.
Your executable is called makefile. When you run make, it tries to parse the executable as Makefile. Either rename the executable, or specify the makefile explicitly:
make -f Makefile clean

Writing Makefile in C

I am writing(at first time) a makefile for my program in C. This is my make file:
CC = gcc
FILES = in_one.c in_two.c in_two.h
OUT_EXE = out_executable
build: $(FILES)
$(CC) -o $(OUT_EXE) $(FILES)
clean:
rm -f *.o core
rebuild: clean build
Actually, everything works properly : Gcc compiler doesn't show any errors, but maybe someone could explain what does these lines mean:
clean:
rm -f *.o core
rebuild: clean build
The clean lines say that if you want to make clean it does not depend on anything (nothing behind ":"). Furthermore the rm command deletes all object files.
The rebuild: clean build says that if you want to make rebuild it depends on clean and build. So the first thing to do is clean (= delete all object files) and then make build (= compile all source files). After that there is nothing more to do so make stops.
For a quick start, make recipes have the following syntax:
target: dependency1 dependency2 ... dependencyN
command1
command2
...
command3
So if target needs to be made at first all dependencies (dependency1 - dependencyN) are made. After this is done command1 - commandN are executed in that order.
You are rm (removing) or deleting all (*) the existing .o Files. So the next time you compile or call the make file you are just left with the new ones.
Build: $(Files) is creating the .o so the compiler can link them together into an executable

Resources