How to write makefile to compile with -S and -c? - c

I have a source file test.c and its header test.h, a file main.c and the makefile.
I want to set up my makefile so that it (1) compiles test.c to build an executable test.o,
and (2) compiles test.c to print the assembly code to test.s using -S flag.
I have tried to set up the makefile as I thought would be correct, but this of course doesn't actually run the last test.s line.
FLAGS = -c -Wall
CC = gcc
ASM = -S
all : optimize
optimize: main.o test.o
$(CC) main.o test.o -o optimize
main.o: main.c test.h
$(CC) $(FLAGS) main.c
test.o: test.h test.c
$(CC) $(FLAGS) test.c
test.s: test.h test.c
$(CC) $(ASM) -Wall test.c
Can anyone tell me how I should have structured this differently, to create both test.s and test.o?
I tried to change the optimize: line and the following one to:
optimize: main.o test.o test.s
$(CC) main.o test.o test.s -o optimize
but the linker gave an error multiple definition of 'test'.

Simply add test.s to the line that starts with optimize:.
What this does is add the rule test.s to the dependencies of the optimize line.
You could also add it to the all line, as suggested by Vaughn Cato.
It's important to know that there is a difference between the rule test.s and the file test.s
You can put anything you want as the name of the rule, but by convention you normally just use the filename.
Here's an example Makefile that will do what you want. I put the dep under all so you can just make asm and I also changed the rule name to asm for clarity.
FLAGS = -c -Wall
CC = gcc
ASM = -S
all : optimize asm
optimize: main.o test.o
$(CC) main.o test.o -o optimize
main.o: main.c test.h
$(CC) $(FLAGS) main.c
test.o: test.h test.c
$(CC) $(FLAGS) test.c
asm: test.h test.c
$(CC) $(ASM) -Wall test.c -o test.s
Finally, because you seem a bit shaky on how Makefiles work, (I don't blame you honestly), I suggest reading this tutorial: http://mrbook.org/tutorials/make/

Related

How to resolve GNU make producing a "circular main.c" error

//makefile.conf
.SUFFIXES : .c .o
cc = gcc
CFLAG = -c
OFLAG = -o
O2FLAG = -O2
WPIFLAG = -lwringPi
RM = rm -rf
TARGET_SRCS = main.c
TARGET_OBJS = $(TARGET_SRCS:$.c=$.o)
TARGET_NAMES = $(TARGET_SRCS:$.c=$)
BINARY_NAME = LED_TEST
// makefile
include makefile.conf
$(TARGET_OBJS) : $(TARGET_SRCS)
$(CC) $(O2FLAG) $(CFLAG) $(OFLAG) $^
I'm trying to figure out how gnu make works and how to use it. Yet, I'm a beginner.
I'm trying to use make on my assignment (not mandatory, just my passion) for running simple code which lights up LED by using wiringpi.
Actually there's only one main.c and what I want to make is the makefile that runs
gcc -O2 -c -o main.o main.c
gcc -o main main.o -lwiringPi
Since my last code didn't worked, (constantly getting circular main.c <- main.c dependency dropped error)
I tried to make a code that only runs
gcc -O2 -c -o main.o main.c
but I still get circular main.c error and I don't know what that means.
I tried to look up gnu make manuals but I thought through that, it will take my life to understand.
So I'm trying to see the codes and make one with what I saw.
I think I understand the concept of makefile.conf but still don't understand the function of .SUFFIXES.
I understood it as noticing make that I'll make a rule with .c and .o, codes after that in makefile.conf defines the variables those will be used in makefile.
How can I correct the code? When actual 'assignment' took only five minute including adding comments.
First makefile:
main:
gcc -O2 -c -o main.o main.c
gcc -o main main.o -lwiringPi
When that works perfectly, second makefile:
main: main.o
gcc -o main main.o -lwiringPi
main.o: main.c
gcc -O2 -c -o main.o main.c
When that works perfectly, third makefile:
main: main.o
gcc -o $# $^ -lwiringPi
main.o: main.c
gcc -O2 -c -o $# $<
When that works perfectly, you will be ready for more advanced techniques.
If you are really new, it's often helpful to start off with simple makefiles till you need the extra features.
main: main.c
gcc -O2 -o main -lwiringPi main.c
Note the white space before the gcc is a single tab character.
Once you get the hang of that, you can then substitute various items to make your "make rules" easier to duplicate and maintain. For example, %^ means "every dependent source, so a rewrite of the rule would be
main: main.c
gcc -O2 -o main -lwiringPi $^
Occasionally, you might want to offer easy reconfiguration of the compiler, so if you had a dozen rules, and wanted to configure the compiler all in one place
CC=gcc
main: main.c
$(CC) -O2 -o main -lwiringPi $^
would expand the CC variable to the value gcc at make time. There's an upper limit to the utility of this expansion, for example, if something is "one of many of the same thing" You might not want to declare a variable for that individual item. For example, your WPIFLAG is likely always required, and probably not very successfully reconfigurable. Mabye a loader flags variable makes more sense.
LDFLAGS=-lwiringPi -lm -lwhatever
and a compiler flags variable
CFLAGS=-O2 -Werror -Wfatal-errors
Which would lead to the more sensible
main: main.c
$(CC) $(CFLAGS) -o main $(LDFLAGS) $^
Finally, you can replace the target main in this case, with another special variable. $# which means "the target being built"
main: main.c
$(CC) $(CFLAGS) -o $# $(LDFLAGS) $^
Note that for object files, you are listing all your objects as being dependent on all of your sources. If you want to support independent rules for object building, you need to do something different
main: main.o
$(CC) $(CFLAGS) -o $# $(LDFLAGS) $^
And you'll need rules for each object.
main.o: main.c
$(CC) $(CFLAGS) -c -o $# $(LDFLAGS) $^
but it will become a labor typing this rule for each object. To automate this rule, you will use a pattern based on the file suffixes, and a suffix rule.
.SUFFIXES : .o .c
.c.o :
$(CC) $(CFLAGS) -c $<
Note the rule above relies on the default behavior of $(CC) which is to generate a something.o when something.c is compiled with the -c flag. If you wanted to make the output file explicit
.SUFFIXES : .o .c
.c.o :
$(CC) $(CFLAGS) -c -o $# $<
This Suffix Rule acts as a macro. When someone needs thing.o, it will build it from thing.c if thing.c exists, even if there isn't an explicit rule for thing.c
With this, you can then collect all your object on the original main target. (We will remove CFLAGS, as no compiling will be happening, only linking)
main: main.o other.o first.o list.o end.o
$(CC) -o $# $(LDFLAGS) $^
But some find listing the object to be a pain, and like to put them in a variable
main: $(OBJS)
$(CC) -o $# $(LDFLAGS) $^
which means you will need to declare and set OBJS
OBJS = main.o other.o first.o list.o end.o
But it's sort of weird to track intermediate files, so why not track the actual sources
SOURCES = main.c other.c first.c list.c end.c
Ok, but how will we get the required OBJS from SOURCES? We will derefence SOURCES, modifying the suffixes to .o
OBJS = ${SOURCES:.c=.o}
The end result
SOURCES = main.c other.c first.c list.c end.c
OBJS = ${SOURCES:.c=.o}
CC=gcc
CFLAGS=-O2 -Werror -Wfatal-errors
LDFLAGS=-lwiringPi -lm -lwhatever
.SUFFIXES : .o .c
.c.o :
$(CC) $(CFLAGS) -c -o $# $<
main: ${OBJS}
$(CC) -o $# $(LDFLAGS) $^

Makefile fails with warning message

This is a makefile that fails to link the .o files to make an executeable.
enter code here
CC = c99
CFLAGS = -g -Wall -Wextra -O0
OBJECTS = main.o getoptions.o
P = testprog
$(P): $(OBJECTS)
$(CC) $(OBJECTS) -o $(P)
main.o : main.c
$(CC) $(CFLAGS) $(OBJECTS) -c main.c
getoptions.o : getoptions.c getoptions.h
$(CC) $(CFLAGS) -c getoptions.o
I get this warning:
gcc: warning: getoptions.o: linker input file unused because linking not done
When I manually use:
c99 *.o -o testprog
linking succeeds.
Two issues here:
First, in your target for getoptions.o, you're passing getoptions.o for the -c option. You should be giving it the value of the source file getoptions.c
Second, get rid of $(OBJECTS) in the target for main.o. You don't need to pass in the object files for this step.
With those fixes you'll get a successful compilation:
c99 -g -Wall -Wextra -O0 -c main.c
c99 -g -Wall -Wextra -O0 -c getoptions.c
c99 main.o getoptions.o -o testprog
Edit:
The target line for main.o should be:
main.o : main.c getoptions.h
That way, if getoptions.h changes, main.o gets rebuilt.

C makefile errors

I have a custom header file example.h which has prototypes for a few functions. There is a .C file example.c that I implemented which "includes" (#include "example.h") and has the implementations of the functions that has prototype in example.h. Now, I have another function test.c that calls the functions that are prototyped in example.h and defined in example.c.
My make file is as follows
test: test.o
gcc -o test -g test.o
test.o: test.c example.c example.h
gcc -g -c -Wall test.c
gcc -g -c -Wall example.c
clean:
rm -f *.o test
I get following message for the functions that are defined in example.c
Undefined first referenced
symbol in file
function1 test.o
function2 test.o
function3 test.o
function4 test.o
ld: fatal: Symbol referencing errors. No output written to test
collect2: ld returned 1 exit status
* Error code 1
make: Fatal error: Command failed for target `test'
Any help is most appreciated.
%.o: %.c
gcc -c -g -o $# $^
test: test.o example.o
gcc -o -g $# $^
%.o: %.c This means any *.o file should be builded from its equivalen from c files.
example test.o should be builded from test.c and example.o should be builded from example.c
First of all, you must include the example.o file when generating the executable file : gcc -o test example.o test.o. Then, the dependencies you wrote for target test.o are incorrect. You should split it like this :
test: test.o example.o
gcc -o test test.o example.o
test.o: test.c
gcc -c -Wall test.c
example.o: example.c
gcc -c -Wall example.c
Then, consider the use of variables to store the names of your object files, the flags you want to pass to the linker/compiler etc... This would make your life much easier.
test.o: test.c example.c example.h
gcc -g -c -Wall test.c
gcc -g -c -Wall example.c
as per your code test.o target is calling test.c example.c example.h target which i am not able to see.

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.

Makefile: No rule to make target despite giving target?

While trying to use Make I get the following error:
make: *** No rule to make target `paging.c', needed by `obj/paging.o'. Stop.
But I have given the makefile the rule for making the target. Here's my makefile:
--------
C_SOURCES= main.c monitor.c common.c descriptor_tables.c timer.c paging.c \
fs.c initrd.c task.c syscall.c --------
S_SOURCES= boot.s interrupt.s gdt.s process.s
C_OBJECTS=$(patsubst %.c, obj/%.o, $(C_SOURCES))
S_OBJECTS=$(patsubst %.s, obj/%.o, $(S_SOURCES))
CFLAGS=-c -nostdlib -nostdinc -fno-builtin -fno-stack-protector -m32 -Iheaders
LDFLAGS=-Tlink.ld -melf_i386 --oformat=elf32-i386
ASFLAGS=-felf
all: kern/kernel
.PHONY: clean
clean:
-rm -f obj/*.o kern/kernel
kern/kernel: $(S_OBJECTS) $(C_OBJECTS)
ld $(LDFLAGS) -o $# $^
$(C_OBJECTS): obj/%.o : source/%.c
gcc $(CFLAGS) $< -o $#
vpath %.c source
$(S_OBJECTS): obj/%.o : %.s
nasm $(ASFLAGS) $< -o $#
vpath %.s asem
NOTE: the -------- is not in the original makefile, they are just used to pick the rule I have used.
make output:
nasm -felf asem/boot.s -o obj/boot.o
nasm -fenasm -felf asem/boot.s -o obj/boot.o
nasm -felf asem/interrupt.s -o obj/interrupt.o
nasm -felf asem/gdt.s -o obj/gdt.o
nasm -felf asem/process.s -o obj/process.o
gcc -c -nostdlib -nostdinc -fno-builtin -fno-stack-protector -m32 -Iheaders source/main.c -o obj/main.o
gcc -c -nostdlib -nostdinc -fno-builtin -fno-stack-protector -m32 -Iheaders source/monitor.c -o obj/monitor.o
gcc -c -nostdlib -nostdinc -fno-builtin -fno-stack-protector -m32 -Iheaders source/common.c -o obj/common.o
gcc -c -nostdlib -nostdinc -fno-builtin -fno-stack-protector -m32 -Iheaders source/descriptor_tables.c -o obj/descriptor_tables.o
gcc -c -nostdlib -nostdinc -fno-builtin -fno-stack-protector -m32 -Iheaders source/timer.c -o obj/timer.o
make: *** No rule to make target `source/paging.c', needed by `obj/paging.o'. Stop.
Why is it coming out with the error despite giving it what it needs?
You will have to change the line
$(C_OBJECTS): obj/%.o : %.c
to
$(C_OBJECTS): obj/%.o : source/%.c
edit, in reflect of question change:
void page_fault(registers_t regs)
void page_fault(registers_t *regs);
Compare ;) The two should be the same. According to the code chunk from paging.c, the version in paging.h should be corrected (just remove the *).
Does the file paging.c exist in the same directory as the Makefile?
If it does not, Make will look for a rule to create it. Since there is no rule to create paging.c, it will give you this error.
The error is telling you that "make" cannot find the file "paging.c" anywhere in the vpath or in the current directory, and it has no rule to create "paging.c" from any other source file.
Make sure that you actually have "paging.c" where you think you do, and that it is actually called "paging.c" and not "paging.c " (extra space) or some other unicode special stuff that looks like "paging.c" when you print it out, but isn't.

Resources