Makefile runs but does not clean object files and executable file - c

My makefile runs but it does not execute the cleaning of the object file and executable files, as specified by rm -f $(PROJECT) $(OBJ). What am I doing wrong?
makefile
PROJECT = cfind
HEADERS = $(cfind.h)
OBJ = argv.o globals.o main.o pathInfo.o
C99 = cc -std=c99
CFLAGS = -Wall -pedantic -Werror
$(PROJECT) : $(OBJ)
$(C99) $(CFLAGS) -o $(PROJECT) $(OBJ)
%.o : %.c $(HEADERS)
$(C99) $(CFLAGS) -c $<
clean:
rm -f $(PROJECT) $(OBJ)

When you execute make, it makes whatever target you tell it to make. Unless you tell it make the clean target, or that target is a dependency of the one you did tell it to make, it won't make that target. The main purpose of makefiles and specifying dependencies (rather than just using a build script) is to perform only the required operations. By default, make makes the first target in the makefile.
I think you are missing the whole point of a makefile and the reason you specify dependencies. The reason you have $(PROJECT) : $(OBJ) is so that it knows it doesn't have to make that target if the object files haven't changed.
Why do you want it to rebuild the project even if nothing has changed?

Related

Makefile does not compile the current changes .c file

I am writing a makefile for my program, but whenever i do make in my pwd, it is not showing with the latest changes made in .c file. What am i doing wrong with this ?
web : mweb.o
gcc -o bin/web bin/web.o
mweb.o : src/web.c
gcc -c -std=c99 -Wall src/web.c -o bin/web.o
clean:
rm -f web
It's always wrong for your makefile rules to create files that are not the identical pathname of the target you provided in your rule. So:
<target>: ...
<command>
The <command> must create the file named by <target>.
Here, your <target> in the first rule is web, but the compile command you gave creates the file bin/web. Your <target> on the second rule is mweb.o but the compile command creates the file bin/web.o.
That cannot work.
The best thing to do is use make's $# automatic variable: those are set by make and always contain the files that make expects you to create.
CFLAGS = -std=c99 -Wall
bin/web : bin/mweb.o
$(CC) $(CFLAGS) -o $# $^
bin/mweb.o : src/web.c
$(CC) -c $(CFLAGS) $< -o $#
clean:
rm -f web

Makefile cannot create a seperate Object Folder for simple project

I am using this Makefile Tutorial for understanding how to use Makefiles.
This Question might be a duplicate for this thread but I think I need more clarity here.
My Project structure:
--exercise_14/
--> ex14.c
--> ex14.h
--> main.c
--> Makefile
There is nothing complex about ex14.*, just simple header file with 3 function declarations (ex14.h) and their implementation (ex14.c) and main.c calls them.
My Makefile is as follows:
CC = gcc
CFLAGS = -Wall -g
DEPS = ex14.h
ODIR=obj
_OBJ=ex14.o main.o
OBJ=$(patsubst %,$(ODIR)/%,$(_OBJ))
all: ex14
$(ODIR)/%.o: %.c $(DEPS)
$(CC) $(CFLAGS) -c -o $# $<
ex14: $(OBJ)
$(CC) $(CFLAGS) -o $# $^
clean:
rm -f ex14 $(ODIR)*.o
rm -rf $(ODIR)
I am currently understanding how the patsubst in the file should work and everytime I run
make clean all
I get:
gcc -Wall -g -c -o obj/ex14.o ex14.c
Assembler messages:
Fatal error: can't create obj/ex14.o: No such file or directory
Makefile:16: recipe for target 'obj/ex14.o' failed
make: *** [obj/ex14.o] Error 1
Which makes sense that there is no obj/ folder created and no ex14.o is found for further compilation. A way around is to use mkdir obj and then perform make but I want to avoid that.
Question
What lines should be added to let my Makefile make a folder as ODIR=obj and put all the object files within it?
The correct solution is to make your object files depend on their directory via order-only dependency:
Consider an example where your targets are to be placed in a separate directory, and that directory might not exist before make is run. In this situation, you want the directory to be created before any targets are placed into it but, because the timestamps on directories change whenever a file is added, removed, or renamed, we certainly don’t want to rebuild all the targets whenever the directory’s timestamp changes. One way to manage this is with order-only prerequisites: make the directory an order-only prerequisite on all the targets:
$(ODIR)/%.o: %.c $(DEPS) | $(ODIR)
<same-original-recipe>
$(ODIR):
mkdir -p $#
As commented by others, but you can explicitly put a dependency to the $(ODIR) directory (it must be created before any dependent files ---compilation):
$(OBJS): $(ODIR)
$(ODIR):
mkdir -p $#
This will ensure you have created the $(ODIR) directory before any dependent files (any *.o file) and that it will be created only once.
The final contents of your Makefile should be as this:
CC = gcc
CFLAGS = -Wall -g
DEPS = ex14.h
ODIR=obj
_OBJ=ex14.o main.o
OBJ=$(patsubst %,$(ODIR)/%,$(_OBJ))
all: ex14
$(ODIR)/%.o: %.c $(DEPS)
$(CC) $(CFLAGS) -c -o $# $<
ex14: $(OBJ)
$(CC) $(CFLAGS) -o $# $^
clean:
rm -f ex14 $(ODIR)*.o
rm -rf $(ODIR)
$(OBJ): $(ODIR)
$(ODIR):
mkdir -p $#
EDIT 2
After posting the correct rule I found some errors in the $(patsubst) variable expansion, that made make to fail when not everything was erased.
Following is a correct, optimized Makefile:
$ cat Makefile
CC = gcc
CFLAGS = -Wall -g
DEPS = ex14.h
ODIR=obj
OBJS=ex14.o main.o
POBJS=$(foreach i,$(OBJS),$(ODIR)/$(i))
LIBS= # for example: -lm for math library.
.PHONY: all ex14 clean
$(ODIR)/%.o: %.c
$(CC) $(CFLAGS) -c $< -o $#
all: ex14
ex14: $(POBJS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $# $(POBJS) $(LIBS)
clean:
rm -rf $(ODIR)
$(POBJS): $(ODIR) $(DEPS)
$(ODIR):
mkdir -p $#
putting the dependency on $(DEPS) in the
$(OBJS): $(ODIR) $(DEPS)
makes the automatic default dependency rule for .c -> .o files valid, and not needed anymore in the makefile. Also, I have used P prefix to mean pathed file in POBJS against OBJS (which is the plain list of object files) Also removing recursively the objs subdirectory makes unnecessary to remove the object files first, and then the subdirectory (only the last command is needed) Also, when linking, it is common use, to pass the compiler the $(LDFLAGS) for it to pass them to the linker. And finally, if you have some libraries to include at the end, just use a $(LIBS) library (not needed for your sample).
As stated in one of the comments, the compilation of just one source file makes the $(ODIR) directory to be touched, and all the other files to be out of date, and this will make all the files but the one just compiled to be compiled next time. There's no solution to this problem as there's a circular dependency on this (the objects depend on the directory to exist, and the directory is touched on each compilation which makes the dependency to be triggered again for all the files compiled before the last one) The only possible solution to this problem is to eliminate the dependency on the directory and construct it by hand before calling make.
Berkeley make (pmake or bmake, it depends) has a workaround to this problem, by allowing you to define a .BEGIN dependency, that is to be solved before any other work. You can create the directory there. I think GNU make doesn't have this feature:
.BEGIN:
mkdir -p $(ODIR)
But this is out of scope for this question that is directed to GNU make.

makefile makes weird error

So I wrote a program to calculate Caesar cipher but I think it's not really matter - what matter is that when I'm trying to do make the compiler or who checks the syntax of my makefile is throw an error says :
make: *** No rule to make target 'clean.', needed by 'PHONY'. Stop.
In my directory I have 5 files:
main.c
ceasar.c
ceasar.h
parser.c
parser.h
and the makefile looks like:
PHONY : all clean.
CFLAGS = -c -g -Wall
CXXFLAGS = -o
CC = gcc
OBJECTS = main.o ceasar.o parser.o
EXTRA_SRCS = ceasear.h parser.h
all : ex1
ex1 : $(objects)
$(CC) $(CXXFLAGS) ex1 $(objects)
%.o : %.c $(wildcard $(EXTRA_SRCS))
$(CC) $(CFLAGS) $<
clean:
rm *.o
The makefile should clean the objects files when typed make clean
and the line $(wildcard $(EXTRA_SRCS)) should checks if the c file has header file(parser and caeser, not main).
I'm using ubuntu 15.10 and please help me :)
It's possible to specify fictitious target that has as purpose to execute a sequence of operations. These targets do not specify any dependency and must not appear as the first rule, to be carried out only if they are passed as arguments to make command explicitly. Fictitious target is not a file (the file does not exist) it is used to initiate the execution of the command in each case.
CFLAGS = -c -g -Wall
CXXFLAGS = -o
CC = gcc
OBJECTS = main.o ceasar.o parser.o
EXTRA_SRCS = ceasear.h parser.h
all : ex1
ex1 : $(objects)
$(CC) $(CXXFLAGS) ex1 $(objects)
%.o : %.c $(wildcard $(EXTRA_SRCS))
$(CC) $(CFLAGS) $<
.PHONY: clean
clean: rm *.o
Be careful because the fictitious target may be masked by existing files: if accidentally in the directory it creates a file called the same name of the fictitious target then, as the target has no dependencies, and the file already exists, that file does not need to be updated and then the command list will never be executed.

Rule not recognized in makefile?

I have a basic makefile to compile C files necessary for compiling a shared library, I have an error because the makefile is not recognized:
SOURCES=/home/test/project/sources
OBJECTS=/home/test/project/objects
$(OBJECTS)/%.o:$(SOURCES)/%.c
$(CC) -fPIC -c $^ -o $#
sharedlib: $(OBJECTS)/%.o
$(CC) -shared -o libsharedlib.so $<
When I run make I get that there is no rule for target: $(OBJECTS)/%.o needed by sharedlib. While the rule is written right before sharedlib.
The main problem is that nowhere you are explicitly telling make what your source files are. Start by doing that:
SOURCEDIR=/home/test/project/sources
SOURCES=$(wildcard $(SOURCEDIR)/*.c)
Then, derive the object file names from the source file names by substituting .c for .o:
OBJECTDIR=/home/test/project/objects
OBJECTS=$(patsubst $(SOURCEDIR)/%.c,$(OBJECTDIR)/%.o,$(SOURCES))
You can still keep your generic rule to build object files:
$(OBJECTDIR)/%.o: $(SOURCEDIR)/%.c
$(CC) -fPIC -c $^ -o $#
But you give the explicit list of object files to the rule to make sharedlib:
libsharedlib.so: $(OBJECTS)
$(CC) -shared -o $# $<
Note that I made the name of the rule the same as the file that is being generated. That's important, because calling make twice in a row will then skip building the library a second time. You can always add an alias if you want:
sharedlib: libsharedlib.so
In that case, it's also good to tell make that sharedlib is not a real file:
.PHONY sharedlib
This prevents weird things from happening if you ever did have a file called sharedlib in the directory.
The library rule
sharedlib: $(OBJECTS)/%.o
is not enough to tell Make which objs are needed for the library.
This should work, and gives explicit control on which are the sources/objs pairs you want in the library:
SOURCESDIR=/home/test/project/sources
OBJECTDIR=/home/test/project/objects
OBJLIST = \
$(OBJECTS)/file1.o \
$(OBJECTS)/file2.o
$(OBJECTDIR)/%.o: $(SOURCESDIR)/%.c
$(CC) -fPIC -c $^ -o $#
sharedlib: $(OBJLIST)
$(CC) -shared -o libsharedlib.so $<

Why does my Makefile do nothing?

#
# MakeFile assignment 2
# Variables
CC=gcc
LINK=gcc
CFLAGS=-c -Wall -I.
OBJECT_FILES = cmpsc311-f13-assign2.o a2support.o
#Suffix rules
.SUFFIXES: .c .o
.c.o:
$(CC) -c $(CFLAGS) -o $# $<
#Productions
cmpsc311-f13-assign2 : $(OBJECT_FILES)
$(LINK) $(OBJECT_FILES) -o $#
#Dependencies
cmpsc311-f13-assign2.o : cmpsc311-f13-assign2.c a2support.h
a2support.o : a2support.c a2support.h
clean:
rm cmpsc311-f13-assign2.o
rm a2support.o
Every time I use the command make Makefile it does nothing, is there something wrong with my makefile or is it another issue?
Running the following command also dose nothing:
gcc -o cmpsc311-f13-assign2 cmpsc311-f13-assign2.c a2support.c a2support.h -I.
Every time I use the command make Makefile it does nothing
make Makefile tries to create Makefile. Since you don't have any rule to create it, there's nothing to do.
Usually make is invoked with no arguments; it uses Makefile by default, and tries to make the first target defined (in your case, cmpsc311-f13-assign2).
You can use the -f option to specify a different makefile to use:
make -f foo.mk
or you can use an argument to specify what to build:
make clean
or both:
make -f foo.mk clean
Apart from the answer mentioned above you also need to add a TAB character at line 14.
$(CC) -c $(CFLAGS) -o $# $<

Resources