How to create a makefile in gcc - c

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)

Related

How can I compile a header file and a C file together?

I created a file.h and a file.c how can I compile them on Ubuntu?
You only need to compile your .c file(s), not your .h file(s).
To compile file.c on Ubuntu, you can use GCC:
gcc file.c -o my_program
...or Clang:
clang file.c -o my_program
It is possible to precompile your header files, but you only need precompiled headers in particular cases. More information here.
If file.h is not in the same folder as file.c, you can use GCC or Clang's -I option.
Example if file.h is in the include/ folder:
gcc -I include/ file.c -o my_program
In file.c you still have this instruction, with only the filename:
#include "file.h"
You can also use a more generic approach by the usage of a makefile.
Here is a short example of such a file:
# Declaration of variables
CC = gcc
CC_FLAGS = -w -Werror -Wall
# File names
# "prgoram" will be the name of the output produced from the make process
EXEC = program
#Incorporates all the files with .c extension
SOURCES = $(wildcard *.c)
OBJECTS = $(SOURCES:.c=.o)
# Main target
$(EXEC): $(OBJECTS)
$(CC) $(OBJECTS) -o $(EXEC)
# To obtain object files
%.o: %.c
$(CC) -c $(CC_FLAGS) $< -o $#
# To remove generated files
clean:
rm -f $(EXEC) $(OBJECTS)
To use this utility just make sure that the file itself is within the directory containing your source files and its name is either "makefile" or "Makefile".
To compile the code simply run the following command from your working directory:
make program
This command will automatically link all the source files within your working directory into one executable file with the name of "program". To run the program itself just use the command:
./program
To clean your project and the created executable you can run the command:
make clean
The makefile is very powerful when dealing with larger projects that contain a larger number of source files. Here you can check for more guidance on how to use makefiles. This is also a very detailed tutorial on the topic.
Use following command to compile your program(For GCC Compiler):
gcc file.c -o file
No need to compile file.h file.

Creating a makefile C using all, clean, and other

My professor gave me a code that he already wrote and we had to fill in the rest. Now our task is to create a makefile using multiple targets. These are the directions:
"3. Create a Makefile to create your project. Your makefile should have the following targets (put all at the top)
a.).all Creates all object files and executable files
b.).Wall.o Builds the Wall.o object file from Wall.c
c.).Maze.o Builds the Maze.o object file from Maze.c
d.).DisjointSetADT.o Builds theDisjointSetADT.o object file from DisjointSetADT.c
e.).MazeBuilder.o Builds the MazeBuilder.o object file fromMazeBuilder.c
f.).MazeBuilder Builds the MazeBuilder executable from all object files
g.).clean Deletes all object files and executable files."
This is what I have so far:
all: MazeBuilder
Wall.o: Wall.c
gcc -c -Wall Wall.c
Maze.o: Maze.c
gcc -c -Wall Maze.c
DisjointSetADT.o: DisjointSetADT.c
gcc -c -Wall DisjointSetADT.c
MazeBuilder.o: MazeBuilder.c
gcc -c -Wall MazeBuilder.c
MazeBuilder: MazeBuilder.o Wall.o Maze.o DisjointSetADT.o
gcc MazeBuilder.o Wall.o Maze.o DisjointSetADT.o -o MazeBuilder
clean:
rm -f *.o MazeBuilder
I have no idea why my auto grader says the makefile doesn't work. There are tabs under each target already, not sure why they are not popping in when I copy my code over.
We must proceed in small steps.
Start in a directory that contains the various source files (Wall.c, DisjointSetADT.c and so on) and the makefile. This is essential.
1) Compiling from the command line. Try this command (in the command line, instead of "make"):
gcc -c -Wall Wall.c
This should build Wall.o; if it doesn't then tell us (in a comment to this Answer) exactly what the result was. If it works, remove Wall.o and proceed to...
2) Compiling with Make. Try this:
make Wall.o
This should do exactly the same thing as step 1. If it works, try make clean to remove Wall.o.
3) Build all the object files:
make MazeBuilder.o Wall.o Maze.o DisjointSetADT.o
4) Linking the objects by hand:
gcc MazeBuilder.o Wall.o Maze.o DisjointSetADT.o -o MazeBuilder
5) The whole shebang:
make clean
make MazeBuilder
6) Using the default rule:
make clean
make
Tell us where and how this sequence fails, and we'll try to fix it.

Unix: Project Management with Make

My instructions are:
The steps necessary to produce this program are:
Compile cpp2html.c to produce cpp2html.o. (Important: the source code in this project is C, not C++, and so must be compiled and linked with gcc, not g++.)
Run the command
flex cppscanner.l
to produce the file lex.yy.c from the language description in cppscanner.l.
Compile lex.yy.c to produce lex.yy.o. (This often produces a warning message about extra tokens. Ignore it.)
Link the .o files to produce an executable program named cpp2html
Write a makefile that will carry out these steps. Your makefile should result in only the minimum required amount of steps when any input file to this process is changed. (Note: you will probably not be able to base this makefile upon my self-updating makefile as in the earlier part of the assignment. Instead, you will probably find it necessary to write this one from scratch.
Here is my makefile:
cpp2html: cpp2html.o lex.yy.o
gcc -g -DDEBUG cpp2html.o lex.yy.o
mv a.out cpp2html
lex.yy.o: lex.yy.c
gcc -g -DDEBUG lex.yy.c
lex.yy.c:
flex cppscanner.l
cpp2html.o: cpp2html.c
gcc -g -DDEBUG cpp2html.c
What am I doing wrong here? I get an error message saying:
collect2: error: ld returned 1 exit status
make: *** [cpp2html.o] Error 1
Your makefile does not build 'cpp2html' when invoked:
gcc -g -DDEBUG cpp2html.c
This is due tonight, so any suggestions would be greatly appreciated.
It's complaining about the following:
cpp2html.o: cpp2html.c
gcc -g -DDEBUG cpp2html.c
This line is trying to compile cpp2html.c to a.out.
Change that to
cpp2html.o: cpp2html.c
gcc -g -DDEBUG -c cpp2html.c
Do the same thing for the line that compiles lex.yy.c to lex.yy.o. The -c option tells gcc to only generate the object file and write it to the .o file.
You can take advantage of other options and some built-in variables. Here's a suggestion:
cpp2html: cpp2html.o lex.yy.o
gcc -g -DDEBUG -o $# $?
$# evaluates to the name of the target. $? evaluates to the list of dependencies (the .o files). The -o option tells gcc to write the resulting binary to the specified file name instead of a.out.
You can also take advantage of implicit rules:
%.o : %.c
gcc -g -DDEBUG -c $<
This will build any .c file to the corresponding .o file, so you don't need to repeat the same commands for cpp2html.c and lex.yy.c.
Edit
FWIW, here's how I'd structure the makefile (with annotations; assumes Gnu make):
# Variables used by implicit rules
CFLAGS=-g -DDEBUG -Wall -Werror # flags for gcc
LFLAGS= # flags for flex, currently none
LEX=flex # lexer
CC=gcc # C compiler
# Variables to make life easier
LSRCS=cppscanner.l # All of our flex source files
SRCS=cpp2html.c $(patsubst %.l,%.c,${LSRCS}) # All of our C source files
OBJS=$(patsubst %.c,%.o,${SRCS}) # All of our object files
TARGET=cpp2html # Final target name
${TARGET} : ${OBJS}
${CC} ${CFLAGS} -o $# $^ # Explicit rule to build target
# $# expands to target name
# $^ expands to list of all prerequisites
clean:
rm -rf *.o $(patsubst %.l,%.c,${LSRCS})
That's it. We're relying on implicit rules to build the .l file to a .c file, and to build the .c files to .o files. The implicit rules use the LEX, CC, LFLAGS and CFLAGS variables to run the right commands with the right options. We only need the single explicit rule to build our final executable.
The advantage of structuring a makefile like this is that you can add files to the project without having to add new rules.
I think all of the above is correct; my main box is shut down at the moment so I can't test it. Refer to the Gnu Make manual for more details.

What is the difference between makefile and sh file

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.

how to create a makefile linux

I have the following: a .c code, a .h code plus a .o file and a -lib... library. When I compile the c code with gcc I do:
gcc code.c -o code file.o -library
How to create a makefile?
I currently have with autoconf and automake?
I currently have:
Makefile
all:
gcc code.c -o code file.o -library
clean:
rm -f code
When I compile make I get:
make: Nothing to be done for `all'.
Need some help. Thx
I'm sorry I have to give this answer, but have you tried https://www.google.com/search?q=makefile+tutorial?
Pick one, and learn how to create a Makefile. You don't need the autotools.
It took me 5 minutes to come up with this, by reading Makefile Tutorial:
CC=gcc
CFLAGS=-Wall
CLIBS=-lX11
OUT=code
OBJS=code.o file.o
$(OUT): code.o file.o
$(CC) $(CFLAGS) $(CLIBS) -o $(OUT) $(OBJS)
code.o: code.c
$(CC) $(CFLAGS) -c code.c -o code.o
file.o: file.c
$(CC) $(CFLAGS) -c file.c -o file.o
.PHONY: clean
clean:
rm -rf *.o $(OUT)
If on the computer the -library doesn t exist I want to install it automatically.
This is specific to the distribution used and you need root access on the machine. Doing it like this is not how it's done. Instead, you should create a package specific for your distribution where you specify the dependencies.
For instance, for Ubuntu (since it's the most used distribution), you'd create a .deb file: http://wiki.debian.org/IntroDebianPackaging
This, however, has nothing to do with your initial question.
See this code this may help you.
For example create a C test file "test.c" and then create makefile as shown below.
Makefile
all:
cc -o test test.c
clean:
rm -f test
Save this file as "Makefile"
Run this makefile by make command. It then creates test executable file at present directory
Run the file using ./test
You can use make clean to delete the executable file(test).
For any reference to see Makefile tutorial

Resources