creating a makefile for multiple C files - c

Im having trouble creating a makefile for 5 c programs. I now that each of the c programs are able to compile on its own but when I try to make a makefile I get this error when running make
Makefile:2: *** missing separator. Stop.
The file names that I am trying to put into the makefile are first.c, second.c, third.c, fourth.c, and fifth.c. This is what I have for my makefile as of right now:
program: first.o second.o third.o fourth.o fifth.o
gcc -o program first.o second.o third.o fourth.o fifth.o
first.o: first.c
gcc -c first.c
second.o: second.c
gcc -c second.c
third.o: third.c
gcc -c third.c
fourth.o: fourth.c
gcc -c fourth.c
fifth.o: fifth.c
gcc -c fifth.c

How many times are we going to give the same answer but here is my take on the same thing.
The Makefile should consist of the following:
program: first.o second.o third.o fourth.o fifth.o
gcc -g -o program first.o second.o third.o fourth.o fifth.o
.c.o:
gcc -c -g $<
Where the spaces before the gcc lines are a single tab not spaces. If you use spaces or forget the colon at the end, you will get "missing separator".
The
.c.o:
is the old way to do it but it still works. This creates a default rule to turn .c files into .o files. Since I include the -c option to only compile, I did not bother with the -o $# that would say where to send the output.
Observe, this addresses the "missing separator" issue and produces the one executable that was originally asked for.

Alternatively:
all: first second third fourth fifth
%.o: %.c #Suppress default rule
%: %.c
gcc -o $# $<

This is how it should be formatted:
all: first second third fourth fifth
first: first.c
gcc -o first first.c
second: second.c
gcc -o second second.c
third: third.c
gcc -o third third.c
fourth: fourth.c
gcc -o fourth fourth.c
fifth: fifth.c
gcc -o fifth fifth.c

Related

Why am I getting this error Makefile: No rule to make target 'timer.c', needed by 'timer.o'. Stop

My working directory looks like this:
main.c
Makefile
my_memmove.h
my_memmove.c
c-timer-lib
timer.c
timer.h
My makefile looks like this:
CC := gcc
CFLAGS := -std=gnu99 -g -Wall -Wextra -Ic-timer-lib
TARGET := output
output: main.o my_memmove.o timer.o
$(CC) $(CFLAGS) main.o my_memmove.o timer.o -o $(TARGET)
main.o: main.c
gcc -c main.c
my_memmove.o: my_memmove.c my_memmove.h
gcc -c my_memmove.c
timer.o: c-timer-lib/timer.c c-timer-lib/timer.h
gcc -c c-timer-lib/timer.c -o $#
clean:
rm *.o $(TARGET)
I don't understand why I keep getting the "Makefile: No rule to make target 'timer.c', needed by 'timer.o'. Stop." error. I believe that it's because the timer.c and timer.h files can't be found.
So much confusion here! :)
First, this is definitely wrong:
$(CC) $(CFLAGS) -I main.o ...
The -I main.o tells the compiler that it should use main.o as the name of a directory to search for include files. That clearly won't work. You should remove the -I here.
On to your problem: you have to realize that there are two completely different programs at play here: make which figures out how to run commands, and the commands that are being run, in this case the compiler gcc.
The -I option is an option to the compiler so that the compiler knows where to look for header files that are included by your source code with #include.
That option means nothing to make; it doesn't understand that option. It's just some text to pass to the compiler. Make is looking for the source file timer.c and it can't find it because you haven't told make where it is.
You have to write your rule to look in the correct place, like this:
timer.o: c-timer-lib/timer.c c-timer-lib/timer.h
gcc -c c-timer-lib/timer.c -o $#
(you should always use -o $# so that your compile line puts the output file where make expects to find it, which will be put into the $# variable by make before it evaluates your recipe.)
ETA
Also, are you sure that -DUNITS="ms" is right? We can't tell without seeing how UNITS is used in the source, but I suspect you probably need an extra level of quotes here, like -DUNITS='"ms"'
Really, you are trying to do too much in this makefile. Make already knows how to correctly build object files from source files. If you don't force the issue by writing your own rules, then make's built-in rules will do the job for you. Your makefile can be written like this:
CC := gcc
CFLAGS := -std=gnu99 -g -Wall -Wextra -Ic-timer-lib -DUNITS='"ms"'
TARGET := output
$(TARGET): main.o my_memmove.o c-timer-lib/timer.o
$(CC) $(CFLAGS) $(LDFLAGS) -o $# $^ $(LDLIBS)
my_memmove.o: my_memmove.h
c-timer-lib/timer.o: c-timer-lib/timer.h
clean:
rm *.o $(TARGET)
make doesn't know which headers your source requires so you have to add the prerequisites by hand, although you can add extra rules to allow it to figure that out for itself.

Compiling multiple C and header files with 1 main

[Files in my directory][1]
Need help compiling in a make file.
So I have this link list assignment i'm doing and the directions were.
stringlist.h is supposed to contain the node and the function prototypes
stringlist.c is supposed to have the functions completed that are defined in stringlist.h. BUT stringlist.c is not supposed to contain main at all. Then, namelist.c is supposed to contain main and just have the I/O and its just supposed to call the command functions that are in stringlist.c.
So to compile this we are supposed to create a make file. Whenever I try to I get an error because main doesn't exit in one of the c files. Throughout the term we compiled code like this "gcc -std=gnu99 -m32 -Wall -g -o file file.c"
But it doesn't work.
How would I create the make file? Been spending hours and can't figure it out.
As stated by Jonathan Leffler, the sample Makefile I provided had a few bad ideas. Here's an improvement:
# compiler:
CC = gcc
# compiler flags:
CFLAGS = -g -Wall
# the build target executable:
TARGET = executable
# object files to build:
OBJ = namelist.o stringlist.o
all: $(TARGET)
$(TARGET): $(OBJ)
$(CC) $(CFLAGS) -o $(TARGET) $(OBJ)
Try this:
OBJ := namelist.c stringlist.c
GCC := gcc -g
CFLAGS := -std=gnu99 -m32 -Wall
compile: $(OBJ)
$(GCC) $(CFLAGS) $(OBJ) -o executable

make ignores -std=c99 flag when compiling and linking a C program

I've tried to get my makefile to compile a file that requires -std=c99 to run. In this case, its to get a "for-loop" through.
This is my code, (its been used "tab" before "$(CC)" ):
CC = gcc
CFLAGS = -c -std=c99
...
Download.o : Download.c
$(CC) $(CFLAGS) Download.c
Download.c contains methods used to download elements from the web
Error message
$ make
gcc -c -std=c99 Download.c
gcc Download.c -o Program
Download.c: In function ‘downloadImageparts’:
Download.c:11:2: error: ‘for’ loop initial declarations are only allowed in C99 mode
Download.c:11:2: note: use option -std=c99 or -std=gnu99 to compile your code
Download.c:13:3: error: ‘for’ loop initial declarations are only allowed in C99 mode
make: *** [comp] Error 1
Attemt to debug
If I run gcc -c -std=c99 Download.c in terminal it works fine.
This problems appears when run in Linux.
SOLVED:
I created a dummy project to show my lecturer, in an attempt to solve my problem. In the dummy project all works fine with the code described. For some reason my code works on place but not in the other. If someone reading this having the same problem as me and would like to see an example project. let me know and I'll write the code here. Thanks
You're looking at the wrong rule. Download.c is actually compiling fine, but the linking stage is wrong.
$ make
gcc -c -std=c99 Download.c # Compile
gcc Download.c -o Program # Link
Fix the make rule that links the program. It should probably look something like this:
Program: a.o b.o c.o
$(CC) $(LDFLAGS) -o $# $^ $(LIBS)
While you're at it, I suggest a more complete Makefile will look something like this:
all: Program
clean:
rm -f Program *.o
.PHONY: all clean
# -c is implicit, you don't need it (it *shouldn't* be there)
# CC is also implicit, you don't need it
CFLAGS := -std=c99 -g -Wall -Wextra
Program: a.o b.o c.o
$(CC) $(LDFLAGS) -o $# $^ $(LIBS)
# Make will automatically generate the necessary commands
# You just need to name which headers each file depends on
# (You can make the dependencies automatic but this is simpler)
a.o: a.c header.h
b.o: b.c header.h header2.h
c.o: c.c header.h
Examples of how to do it wrong
Linker flags are actually fairly touchy! Be sure to type in the line above exactly as I have written it, and don't assume that what you've written is equivalent. Here are some examples of slightly different commands that are wrong and should not be used:
# WRONG: program must depend on *.o files, NOT *.c files
Program: a.c b.c c.c
$(CC) ...
# WRONG: -c should not be in CFLAGS
CFLAGS := -c -std=c99
Program: a.o b.o c.o
# WRONG: $(CFLAGS) should not be here
# you are NOT compiling, so they do not belong here
$(CC) $(CFLAGS) $(LDFLAGS) -o $# $^ $(LIBS)
# WRONG: $(LIBS) MUST come at the end
# otherwise linker may fail to find symbols
$(CC) $(LDFLAGS) -o $# $(LIBS) $^
# WRONG: do not list *.o files, use $^ instead
# otherwise it is easy to get typos here
$(CC) $(LDFLAGS) -o $# a.o b.o c.o $(LIBS)
# WRONG: $(LDFLAGS) must be at the beginning
# it only applies to what comes after, so you
# MUST put it at the beginning
$(CC) -o $# $(LDFLAGS) $^ $(LIBS)
# WRONG: -c flag disables linking
# but we are trying to link!
$(CC) $(LDFLAGS) -c -o $# $^ $(LIBS)
# WRONG: use $(CC), not gcc
# Don't sabotage your ability to "make CC=clang" or "make CC=gcc-4.7"
gcc $(LDFLAGS) -o $# $^ $(LIBS)
# WRONG: ld does not include libc by default!
ld $(LDFLAGS) -o $# $^ $(LIBS)
I see the same results if I use spaces instead of tabs inside the makefile, and the output of make shows that the rule isn't being used:
$ make
cc -c -o Download.o Download.c
Download.c: In function ‘main’:
Download.c:4:3: error: ‘for’ loop initial declarations are only allowed in C99 mode
Download.c:4:3: note: use option -std=c99 or -std=gnu99 to compile your code
make: *** [Download.o] Error 1
Try a tab before the line starting with gcc.
After seeing the update to the original question:
$ make
gcc -c -std=c99 Download.c
gcc Download.c -o Program
The first (compile) line shows no errors.
It's the second line, which re-compiles Download.c, that fails.
I think you want to link the .o files to create the executable Program here, as Dietrich Epp suggests.

Compiling to 32-bit using make

I am trying to compile a very simple program using the -m32 flag.
If I try to do this using gcc -m32 it works just fine(I have the needed libs)
Yet, when I add this flag to my flags in a makefile, I get a weird error
This is the makefile that I have
CC=gcc
CFLAGS=-m32 -O1 -W -Wall -pedantic -std=c99
all: main.o
$(CC) -o main main.o
rm main.o
clean:
rm main
The error that I receive is the following
gcc -o main main.o
/usr/bin/ld: i386 architecture of input file `main.o' is incompatible with i386:x86-64 output
collect2: ld returned 1 exit status
make: *** [all] Error 1
Can someone please tell me what does this mean? and how can I fix it?
As for the code, the code does NOTHING except printing 'hello world'
I am using GCC 4.4.3 under Linux 2.6.35 64-bits
Your mistake is that you don't pass -m32 to the linker.
You actually need to change your Makefile to look like this:
CC=gcc
CFLAGS=-m32 -O1 -W -Wall -pedantic -std=c99
LDFLAGS = -m32
all: main.o
$(CC) $(LDFLAGS) -o main main.o
rm main.o
clean:
rm main
An even better approach would be the following Makefile:
CC=gcc
CFLAGS=-m32 -O1 -W -Wall -pedantic -std=c99
LDFLAGS=-m32
.INTERMEDIATE: main.o
all: main
main: main.o
clean:
-rm main
In the later you just say that main depends on main.o and GNU Make will invoke the linker with the LDFLAGS as arguments for you as it invokes the compiler with the CFLAGS as arguments for the main.o
"The targets which .INTERMEDIATE depends on are treated as intermediate files. See section Chains of Implicit Rules. .INTERMEDIATE with no dependencies marks all file targets mentioned in the makefile as intermediate." Special Built-in Target Names
You should inform the linker as well about the architecture being 32-bit. Try adding
LD = $(CC)
LDFLAGS = -m32
to your Makefile and change
$(CC) -o main main.o
to
$(LD) $(LDFLAGS) -o main $^
and it shoud work.
(Why it worked? If you use GCC to compile and link your code in one step, all the relevant flags and options will be passed down not only to the compiler but to the linker as well.)

Have my makefile show me compile errors?

exedarken: darken.c
gcc -o exedarken darken.c
exeimagestats: imagestats.c
gcc -o exeimagestats imagestats.c
exelighten: lighten.c
gcc -o exelighten lighten.c
exerotate: rotate.c
gcc -o exerotate rotate.c
exeflip: flip.c
gcc -o exeflip flip.c
exematte: matte.c
gcc -o exematte matte.c
Theres my makefile. Is there a way for when I execute this makefile, I get to see the compile errors I get?
By default, make prints the output of any command it executes, ie if there are compilation errors, they should be shown.
On an unrelated note: repeating yourself is bad; your makefile can be simplified to
executables := exedarken exeimagestats exelighten exerotate exeflip exematte
$(executables) : exe% : %.c
gcc -o $# $<
Write in console:
make VERBOSE=1

Resources