I'm trying to make a Makefile for my program. It is so difficult because i've read a lot of guide but none is clear. I have 3 files : main.c , library.c , library.h . Main.c and library.c depend on library.h . The structure of my directory project is formed by :
MyProject directory -> Build directory and Exercise1 directory -> all of my files . In compiler I wrote make and it compiled ; then when I write make execute command, it gives me this error:
cd ../build; ./test
Error: No such file or directory
makefile:23: recipe for target 'execute' failed
make: *** [execute] Error 1
MAKEFILE
CC=gcc
CFLAGS=-Wall
ODIR=../build
DIR = build
.PHONY: all
all: main.o library.o test
$(ODIR)/%.o: %.c $(DEPS)
$(CC) -std=c99 -c -o $# $< $(CFLAGS)
library.o: library.c library.h
$(CC) -std=c99 -c -o $(ODIR)/$# $< $(CFLAGS)
main.o: main.c library.h
$(CC) -std=c99 -c -o $(ODIR)/$# $< $(CFLAGS)
test: $(ODIR)/library.o $(ODIR)/main.o
$(CC) -std=c99 -o $(ODIR)/$# $^ $(CFLAGS)
execute:
cd $(ODIR); ./test
clean:
rm -f $(ODIR)/*.o
These lines:
execute:
cd $(ODIR); ./test
tell make that, when you give the command make execute, it should change the working directory to $(ODIR) and then execute ./test, which means to execute the file test in the current working directory. However, there is no file test in the $(ODIR) directory because you have not built it yet.
You can make that file by executing make test, but that is a bad way to do it. It is better to tell make that the execute target depends on $(ODIR)/test:
execute: $(ODIR)/test
cd $(ODIR); ./test
Then we should change the rule for test to $(ODIR)/test:
$(ODIR)/test: $(ODIR)/library.o $(ODIR)/main.o
$(CC) -std=c99 -o $(ODIR)/$# $^ $(CFLAGS)
Next, delete the rule for all and the .PHONY rule. A rule for all should be used when a makefile can make several different final targets, like ProgramA, ProgramB, and ProgramC, and you want one target that makes all of them. It should not be used to make all of the intermediate object files for a target. The intermediate files should arise out of the rules for building a final target.
Then delete the rules for library.o and main.o. Those are names for files in the current directory, but you are building in $(ODIR). We will let the pattern rule for $(ODIR)/%.o build those.
But we need to fix the pattern rule. It uses DEPS, but that is not defined. Add a line above that says what all the object files depend on:
DEPS=library.h
Nothing in the makefile uses DIR, so delete the line DIR = build.
Finally, you might want to put the execute target first, so that it is the default. Then your makefile is:
CC=gcc
CFLAGS=-Wall
ODIR=../build
DEPS=library.h
execute: $(ODIR)/test
cd $(ODIR); ./test
$(ODIR)/%.o: %.c $(DEPS)
$(CC) -std=c99 -c -o $# $< $(CFLAGS)
$(ODIR)/test: $(ODIR)/library.o $(ODIR)/main.o
$(CC) -std=c99 -o $(ODIR)/$# $^ $(CFLAGS)
clean:
rm -f $(ODIR)/*.o
You might also change the command for clean to remove test:
rm -f $(ODIR)/*.o $(ODIR)/test
Related
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
I am creating a C project as an assignment. Besides source files, it has to include a Makefile, which has to compile executable "solution" with command "make" and another executable "solution.gdb" complied with extra "-g" parameter with command "make debug". In order to do so, I decided to make separate set of objects file ("*.do" files).
Command "make clean", however, has to remove all objects and executable files from directory. The problem arises when I try to use "make clean" command, after only using one command ("make" or "make debug"), because it tries to remove non-existent files.
Example error message:
rm solution.o tree.o list.o commands.o solution.do tree.do list.do commands.do solution solution.gdb
rm: cannot remove 'solution.o': No such file or directory
rm: cannot remove 'tree.o': No such file or directory
rm: cannot remove 'list.o': No such file or directory
rm: cannot remove 'commands.o': No such file or directory
rm: cannot remove 'solution': No such file or directory
Makefile:30: recipe for target 'clean' failed
make: [clean] Error 1 (ignored)
Is there away to modify "make clean" instructions, so these errors does not show up? Or is it better to do it in a completely other way?
Thanks in advance for all the answers.
Makefile:
CC = gcc
CFLAGS = -Wall -Werror -Wextra
DEBUG_CFLAGS = -g $(CFLAGS)
sources = solution.c tree.c list.c commands.c
objects = $(sources:.c=.o)
debug_objects = $(sources:.c=.do)
solution: $(objects)
$(CC) -o $# $^
%.o: %.c
$(CC) -c $(CFLAGS) -o $# $<
%.do: %.c
$(CC) -c $(DEBUG_CFLAGS) -o $# $<
solution.o solution.do: tree.h commands.h
commands.o commands.do: tree.h commands.h
tree.o tree.do: list.h tree.h
.PHONY: debug
debug: $(debug_objects)
$(CC) -o solution.gdb $^
.PHONY: clean
clean:
-rm $(objects) $(debug_objects) solution solution.gdb
Use the -f option to rm. That option tells rm to ignore non-existent files and not prompt for confirmation.
clean:
rm -f $(objects) $(debug_objects) solution solution.gdb
Folder structure:
Makefile
rect_01.c
rect_02.c
square_01.c
Makefile (relevant parts):
%.c:
echo 'Building $# for $(PLATFORM)...'
$(CC) $(CFLAGS) $# -o '$(DESTDIR)/$*'
Command:
make rect_01.c PLATFORM=FOO
Problem - gave me the output:
'rect_01.c up already to date'
So I tried a hack and added a dependency which I added to .Phony,
so that %.c should be executed every time. But now it tries to compile my
makefile even it hasn't the extension .c.
I wrote the following updated makefile (relevant parts):
.PHONY: phonyDummy
%.c: phonyDummy
echo 'Building $# for $(PLATFORM)...'
$(CC) $(CFLAGS) $# -o '$(DESTDIR)/$*'
Which gives me the following output:
make rect_01.c PLATFORM=LINUX_X86
echo 'Building Makefile.c for LINUX_X86...'
Building Makefile.c for LINUX_X86...
g++ -Wall -g Makefile.c -o '../Executables/Makefile'
Makefile: file not recognized: File format not recognized
Makefile:55: recipe for target 'Makefile.c' failed
make: *** [Makefile.c] Error 1
Can you explain this behaviour?
You should learn more about Makefile. You mix two important things: target and dependency.
The target is a file (in most cases) which should create with a rule. The dependency is the "source".
If you write:
%.c:
echo 'Building $# for $(PLATFORM)...'
$(CC) $(CFLAGS) $# -o '$(DESTDIR)/$*'
it means: "I want to create files with .c extension". You don't want to create .c files because you've many (three) .c files. The make checks the rect_01.c: it exists and it's up-to-date because it hasn't any dependency (after the : there isn't anything).
I think you want to build rect_01.so (or similar) - this is the target! So you want similar:
%.o: %.c
echo 'Building $# for $(PLATFORM)...'
$(CC) $(CFLAGS) -o $# $<
In this case if you want to build rect_01.o you should run make rect_01.o. The $(CC) will run if rect_01.o doesn't exist or older than rect_01.c (so the source rect_01.c is newer and doesn't rebuild yet).
#
# 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 $# $<
gcc 4.7.2
c89
GNU Make 3.82
I am trying compile this program I have using this Makefile. I have only 1 src file at the moment, but I will have more later to include.
I am trying to get the Makefile to create the bin directory if it doesn't exist and put the binary executable in there.
INC_PATH=-I/home/dev_tools/apr/include/apr-1
LIB_PATH=-L/home/dev_tools/apr/lib
LIBS=-lapr-1
RUNTIME_PATH=/home/dev_tools/apr/lib
CC=gcc
CFLAGS=-Wall -Wextra -g -m32 -D_DEBUG -D_THREAD_SAFE -D_REENTRANT -D_LARGEFILE64_SOURCE -O2 $(INC_PATH)
OBJECTS=timeout.o
EXECUTABLE=bin/to
all: build $(EXECUTABLE)
$(EXECUTABLE):
$(CC) -m32 -o $# -Wl,-rpath,$(RUNTIME_PATH), $(LIB_PATH) $(OBJECTS) $(LIBS)
build:
#mkdir -p bin
clean:
rm -rf *~ timeout *.o
I am getting this error:
make
gcc -m32 -o bin/to -Wl,-rpath,/home/dev_tools/apr/lib, -L/home/dev_tools/apr/lib timeout.o -lapr-1
gcc: error: timeout.o: No such file or directory
make: *** [bin/to] Error 1
When I remove the $(OBJECTS) I get the following:
gcc -m32 -o bin/to -Wl,-rpath,/home/dev_tools/apr/lib, -L/home/dev_tools/apr/lib -lapr-1
/usr/bin/ld: cannot find : No such file or directory
collect2: error: ld returned 1 exit status
make: *** [bin/to] Error 1
Not sure where I am going wrong with this.
You have not specified how to build the target timeout.o.
You need to add the following code:
timeout.o: timeout.c
$(CC) $(CFLAGS) -c -o $# $<
If you end up with more source file that you need compiled, you can use a pattern matching rule like this:
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $#
Makefiles can be a bit tricky. Because you want to continue adding more objects to your OBJECT variable, I would actually add a prerequisite to EXECUTABLE to make sure all of your objects are compiled. From there, the automatic rule inference should take care of the rest.
Basically replace the line with:
$(EXECUTABLE): $(OBJECTS)
$(CC) -m32 -o $# -Wl,-rpath,$(RUNTIME_PATH), $(LIB_PATH) $(OBJECTS) $(LIBS)
Its showing error because make is not able to find timeout.o file in the current directory.
If you have timeout.c file then add the following to your makefile
OBJECTS: timeout.c
$(CC) -c timeout.c