Compiling multiple .c and .h files - c

My program is divided into 6 files:
list.h (Containing basic list struct info and function prototypes)
list.c (Containg the implementation of the above)
search_tree.h (Containing basic tree struct info and function prototypes)
search_tree.c (Containing the implementation of the above, and includes list.h)
search.h ( again, prototypes of functions )
search.c (implementation of the aobve functions)
main.c ( Requires all of the above in order to run )
I cant seem to figure out what the makefile should be, i've tried the one below but it doesnt work and i get errors of structs and functions not implemented.
myprog: list.o search_tree.o search.o main.o
gcc -o myprog list.o search_tree.o search.o main.o
list.o: list.c list.h
gcc -c list.c
search_tree.o: search_tree.c search_tree.h
gcc -c search_tree.c
search.o: search.c search.h
gcc -c search.c
main.o: search.h search_tree.h list.h hash_table.h
gcc -c main.c

You do not need to explicitly create a rule for each file - make has a number of implicit rules that already do 90% of what you need. Your makefile can be as simple as
CC=gcc
CFLAGS=-std=c11 -pedantic -Wall -Werror # my usual compiler flags
LDFLAGS= # specify additional libraries and library search paths here
myprog: main.o search.o search_table.o list.o
$(CC) -o $# $(LDFLAGS) $?
clean:
rm -rf myprog *.o
There's already an implicit rule to build .o files from .c files, so you don't need to create your own unless you want to override the default, which is
%.o : %.c
$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $#
You do need the explicit myprog rule to link the object files into the executable since the executable name doesn't match any of the source or object file names. $# expands to the target name, myprog, and $? expands to the list of prerequisites for the target (i.e., the object files). $< expands to the first name in the list of prerequisites.
This doesn't cover header file dependencies, but your project is small enough for that to not be too much of an issue. However, give this article a read for one way to handle that.

Similar to John's proposal with a small bug fixed ($^ automatic variable instead of $?), a bit more automation (wildcard to search for the C source files) and with dependencies added for the header files ($(OBJS): %.o: %.h static pattern rule):
EXEC := myprog
OBJS := $(patsubst %.c,%.o,$(wildcard *.c))
$(EXEC): $(OBJS)
$(CC) -o $# $(LDFLAGS) $^
$(OBJS): %.o: %.h
clean:
rm -f $(EXEC) $(OBJS)

Related

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 $<

libgcrypt-config --libs: no such file or directory

I'm using gcrypt, but my compiler seems to unable to find it. Here is my makefile. function.c is a function source file containing functions I defined; I also wrote a header file miao.h with function declaration, and gcrypt.h is included in it. main.c is a source file including miao.h. When I do make: .Could anyone help me? This bothers me so long.
CC = gcc
CFLAGS = 'libgcrypt-config --cflags'
LIBS = 'libgcrypt-config --libs'
OBJS = function.o main.o main
all: $(OBJS)
function.o: function.c
$(CC) -c function.c $(CFLAGS)
main.o: main.c
$(CC) -c main.c $(CFLAGS)
main: main.o function.o
$(CC) -o main main.o function.o $(LIBS)
clean:
rm $(OBJS)
the makefile should be written more like the following:
caveat: I was unable to test the makefile as I do not have libgcrypt-config available.
Per the web site: https://gnupg.org/documentation/manuals/gcrypt/Building-sources.html the libgcrypt-config is an executable so should be surrounded by back-ticks, not single quotes so it will be executed in the current shell.
(back ticks on stackoverflow will result in emphasised text but should still be visible as to where they should be placed.)
Note: where I have placed <tab> your actual makefile needs to have a tab character
Note: targets, like all and clean do not produce a file with the same name, so early in the file there needs to be the statement: .PHONY: all clean
when defining a macro, use := rather than = so the macro is only evaluated once.
Any calls to shell functions should be incorporated via a macro, so it is easy to make a change. In general it is best to include the path to the shell function: I wrote this on Linux, your path may be different. Specifying the actual path becomes very important when cross compiling or there are duplicate names visible via the $PATH statement (as can easily be the case with gcc)
Note: the actual libgcrypt-config executable must be in visible via your $PATH environment variable.
Note: all the individual compile statements could be reduced to the following two lines: (and nothing else needed for the compiles)
%.o: %.c
<tab>$(CC) -c $< -o $# -I. $(CFLAGS)
Note: do not place the contents of a rule where the dependencies is expected. This error was noted in the clean: target
the proposed makefile follows:
CC := /usr/bin/gcc
RM := /usr/bin/rm
CFLAGS := `libgcrypt-config --cflags`
LIBS := `libgcrypt-config --libs`
OBJS := function.o main.o main
TARGET := main
.PHONY: all clean
all: $(TARGET)
function.o: function.c
<tab>$(CC) -c function.c $(CFLAGS) -o function.o -I.
main.o: main.c
<tab>$(CC) -c main.c $(CFLAGS) -o main.o -I.
$(TARGET): $(OBJS)
<tab>$(CC) -o $(TARGET) $(OBJS) $(LIBS)
clean:
<tab>$(RM) -f $(OBJS)

makefile add list of header files .h with no .c [duplicate]

I have the following makefile that I use to build a program (a kernel, actually) that I'm working on. Its from scratch and I'm learning about the process, so its not perfect, but I think its powerful enough at this point for my level of experience writing makefiles.
AS = nasm
CC = gcc
LD = ld
TARGET = core
BUILD = build
SOURCES = source
INCLUDE = include
ASM = assembly
VPATH = $(SOURCES)
CFLAGS = -Wall -O -fstrength-reduce -fomit-frame-pointer -finline-functions \
-nostdinc -fno-builtin -I $(INCLUDE)
ASFLAGS = -f elf
#CFILES = core.c consoleio.c system.c
CFILES = $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
SFILES = assembly/start.asm
SOBJS = $(SFILES:.asm=.o)
COBJS = $(CFILES:.c=.o)
OBJS = $(SOBJS) $(COBJS)
build : $(TARGET).img
$(TARGET).img : $(TARGET).elf
c:/python26/python.exe concat.py stage1 stage2 pad.bin core.elf floppy.img
$(TARGET).elf : $(OBJS)
$(LD) -T link.ld -o $# $^
$(SOBJS) : $(SFILES)
$(AS) $(ASFLAGS) $< -o $#
%.o: %.c
#echo Compiling $<...
$(CC) $(CFLAGS) -c -o $# $<
#Clean Script - Should clear out all .o files everywhere and all that.
clean:
-del *.img
-del *.o
-del assembly\*.o
-del core.elf
My main issue with this makefile is that when I modify a header file that one or more C files include, the C files aren't rebuilt. I can fix this quite easily by having all of my header files be dependencies for all of my C files, but that would effectively cause a complete rebuild of the project any time I changed/added a header file, which would not be very graceful.
What I want is for only the C files that include the header file I change to be rebuilt, and for the entire project to be linked again. I can do the linking by causing all header files to be dependencies of the target, but I cannot figure out how to make the C files be invalidated when their included header files are newer.
I've heard that GCC has some commands to make this possible (so the makefile can somehow figure out which files need to be rebuilt) but I can't for the life of me find an actual implementation example to look at. Can someone post a solution that will enable this behavior in a makefile?
EDIT: I should clarify, I'm familiar with the concept of putting the individual targets in and having each target.o require the header files. That requires me to be editing the makefile every time I include a header file somewhere, which is a bit of a pain. I'm looking for a solution that can derive the header file dependencies on its own, which I'm fairly certain I've seen in other projects.
As already pointed out elsewhere on this site, see this page:
Auto-Dependency Generation
In short, gcc can automatically create .d dependency files for you, which are mini makefile fragments containing the dependencies of the .c file you compiled.
Every time you change the .c file and compile it, the .d file will be updated.
Besides adding the -M flag to gcc, you'll need to include the .d files in the makefile (like Chris wrote above).
There are some more complicated issues in the page which are solved using sed, but you can ignore them and do a "make clean" to clear away the .d files whenever make complains about not being able to build a header file that no longer exists.
You could add a 'make depend' command as others have stated but why not get gcc to create dependencies and compile at the same time:
DEPS := $(COBJS:.o=.d)
-include $(DEPS)
%.o: %.c
$(CC) -c $(CFLAGS) -MM -MF $(patsubst %.o,%.d,$#) -o $# $<
The '-MF' parameter specifies a file to store the dependencies in.
The dash at the start of '-include' tells Make to continue when the .d file doesn't exist (e.g. on first compilation).
Note there seems to be a bug in gcc regarding the -o option. If you set the object filename to say obj/_file__c.o then the generated _file_.d will still contain _file_.o, not obj/_file_c.o.
This is equivalent to Chris Dodd's answer, but uses a different naming convention (and coincidentally doesn't require the sed magic. Copied from a later duplicate.
If you are using a GNU compiler, the compiler can assemble a list of dependencies for you. Makefile fragment:
depend: .depend
.depend: $(SOURCES)
rm -f ./.depend
$(CC) $(CFLAGS) -MM $^>>./.depend;
include .depend
There is also the tool makedepend, but I never liked it as much as gcc -MM
You'll have to make individual targets for each C file, and then list the header file as a dependency. You can still use your generic targets, and just place the .h dependencies afterwards, like so:
%.o: %.c
#echo Compiling $<...
$(CC) $(CFLAGS) -c -o $# $<
foo.c: bar.h
# And so on...
Basically, you need to dynamically create the makefile rules to rebuild the object files when the header files change. If you use gcc and gnumake, this is fairly easy; just put something like:
$(OBJDIR)/%.d: %.c
$(CC) -MM -MG $(CPPFLAGS) $< | sed -e 's,^\([^:]*\)\.o[ ]*:,$(#D)/\1.o $(#D)/\1.d:,' >$#
ifneq ($(MAKECMDGOALS),clean)
include $(SRCS:%.c=$(OBJDIR)/%.d)
endif
in your makefile.
Over and above what #mipadi said, you can also explore the use of the '-M' option to generate a record of the dependencies. You might even generate those into a separate file (perhaps 'depend.mk') which you then include in the makefile. Or you can find a 'make depend' rule which edits the makefile with the correct dependencies (Google terms: "do not remove this line" and depend).
Simpler solution: Just use the Makefile to have the .c to .o compilation rule be dependent on the header file(s) and whatever else is relevant in your project as a dependency.
E.g., in the Makefile somewhere:
DEPENDENCIES=mydefs.h yourdefs.h Makefile GameOfThrones.S07E01.mkv
::: (your other Makefile statements like rules
::: for constructing executables or libraries)
# Compile any .c to the corresponding .o file:
%.o: %.c $(DEPENDENCIES)
$(CC) $(CFLAGS) -c -o $# $<
None of the answers worked for me. E.g. Martin Fido's answer suggests gcc can create dependency file, but when I tried that it was generating empty (zero bytes) object files for me without any warnings or errors. It might be a gcc bug. I am on
$ gcc --version gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-16)
So here's my complete Makefile that works for me; it's a combination of solutions + something that wasn't mentioned by anyone else (e.g. "suffix replacement rule" specified as .cc.o:):
CC = g++
CFLAGS = -Wall -g -std=c++0x
INCLUDES = -I./includes/
# LFLAGS = -L../lib
# LIBS = -lmylib -lm
# List of all source files
SRCS = main.cc cache.cc
# Object files defined from source files
OBJS = $(SRCS:.cc=.o)
# # define the executable file
MAIN = cache_test
#List of non-file based targets:
.PHONY: depend clean all
## .DEFAULT_GOAL := all
# List of dependencies defined from list of object files
DEPS := $(OBJS:.o=.d)
all: $(MAIN)
-include $(DEPS)
$(MAIN): $(OBJS)
$(CC) $(CFLAGS) $(INCLUDES) -o $(MAIN) $(OBJS) $(LFLAGS) $(LIBS)
#suffix replacement rule for building .o's from .cc's
#build dependency files first, second line actually compiles into .o
.cc.o:
$(CC) $(CFLAGS) $(INCLUDES) -c -MM -MF $(patsubst %.o,%.d,$#) $<
$(CC) $(CFLAGS) $(INCLUDES) -c -o $# $<
clean:
$(RM) *.o *~ $(MAIN) *.d
Notice I used .cc .. The above Makefile is easy to adjust for .c files.
Also notice importance of these two lines :
$(CC) $(CFLAGS) $(INCLUDES) -c -MM -MF $(patsubst %.o,%.d,$#) $<
$(CC) $(CFLAGS) $(INCLUDES) -c -o $# $<
so gcc is called once to build a dependency file first, and then actually compiles a .cc file. And so on for each source file.
I believe the mkdep command is what you want. It actually scans .c files for #include lines and creates a dependency tree for them. I believe Automake/Autoconf projects use this by default.

When I use "gcc" in makefile, after making it, I got a "cc" output

For example:
There are 3 source files {main.c test1.c test2.c} in the directory
and a directory file named test3,
and there is a source file named test.c in the directory of test3.
Now I want to create a makefile to compile and link these four source files.
And this is my Makefile:
# Cancel statement "CC=gcc"
src:=$(wildcard *.c) test3.c
obj:=$(patsubst %.c,%.o,$(src))
main:$(obj)
gcc -o main $(obj)
.PHONY:clean
clean:
rm *.o *~
When I called make to compile them, I got a output like this:
cc -c -o main.o main.c
cc -c -o test1.o test1.c
cc -c -o test2.o test2.c
cc -c -o test3.o test3/test3.c
gcc -o main main.o test1.o test2.o test3.o
I know 'cc' is linked to 'gcc' in Linux.
What I don't understand is why did Make call cc to compile these four source files, but call gcc to link the object files?
You changed one rule: the one that links the program main from the object files. And when make did that link, you can see it used gcc.
You didn't do anything to change the built-in rules that make is using to compile the object files, so they use the default (the value of the variable CC) which is cc.
You wrote only the rule to link the object files, and allowed Make to use its default rule to decide how to build the object files from the source files.
GNU Make will expose its rules if you ask it with --print-data-base. In this case, it tells us
%.o: %.c
# recipe to execute (built-in):
$(COMPILE.c) $(OUTPUT_OPTION) $<
and
COMPILE.c = $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
and finally
CC = cc
This explains why Make uses cc to compile your C sources. To change that, simply set CC = gcc. Here's a complete Makefile which does that and also makes best use of Make's built-in rules, to help when you need to extend it:
src := $(wildcard *.c) test3.c
obj := $(patsubst %.c,%.o,$(src))
CC = gcc
main: $(obj)
$(LINK.c) -o $# $^ $(LDLIBS)
.PHONY: clean
clean:
$(RM) *.o *~

make file, Is this look ok?

all: run
run: test.o list.o matrix.o smatrix.o
gcc test.o list.o matrix.o smatrix.o -o matrix-mul
list.o: list.c list.h
gcc -g -c list.c
matrix.o: matrix.c matrix.h
gcc -g -std=c99 -c -o matrix.o matrix.c
smatrix.o: smatrix.c smatrix.h
gcc -g -c -o smatrix.o smatrix.c
test.o: test.c test.h
gcc -g -c test.c
I was having lots of problems to make a makefile and I finally got this working. And I just want to make sure these are ok (not just for making program running but in term of a good make file)
One question is that why do matrix.o and smatrix.o have .o files in the line gcc -g -c ... where as list.o and test.o don't have that line..
I had to add -std=c99 because I was getting some weird for loop error but still don't understand why I need to put matrix.o in the line..
The file is OK-ish. It is not very easily maintainable.
This website has a really good tutorial on how to make nice makefiles:
http://mrbook.org/blog/tutorials/make/
Especially look at the last example:
CC=g++
CFLAGS=-c -Wall
LDFLAGS=
SOURCES=main.cpp hello.cpp factorial.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=hello
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o $#
.cpp.o:
$(CC) $(CFLAGS) $< -o $#
This should show you how to enhance maintainability (add extra files to SOURCES, and the rest is done automatically.
The below file supports make all make depend and make clean - you only need to change the first lines. Remember to make depend if you change includes in any file.
TARGET:=matrix-mul
SOURCES:=test.c list.c matrix.c smatrix.c
OBJECTS:=$(SOURCES:%.c=%.o)
CC=gcc
CFLAGS=-g -std=c99 -Wall
LD=gcc
LDFLAGS=
# First target - simply say that we want to produce matrix-mul
all: $(TARGET)
# To create the target we need all .o files, and we link with LD/LDFLAGS
# $# is the file we're making, aka matrix-mul
$(TARGET): $(OBJECTS)
$(LD) -o $# $(OBJECTS) $(LDFLAGS)
#Creating a .o from a .c
# $< is the c file, $# is the corresponding .o file
.c.o:
$(CC) $(CFLAGS) -c $< -o $#
# Regenerate dependencies
depend:
$(CC) $(CFLAGS) -MM $(SOURCES) > .depend
# Remove produced files
clean:
rm -rf $(OBJECTS) $(TARGET) .depend
# If there's no dependency file, create it
.depend: depend
# Include the autogenerated dependency file
include .depend
EDIT: If you want this even more generic, you can replace the SOURCE:= line with:
SOURCES:=$(wildcard *.c)
This makefile will then simply build TARGET from all .c files in the current directory.
One thing I would highly suggest here would be to add a clean target that deletes all your intermediate files (probably all the .o files), like so:
clean:
rm *.o
For extra credit, put all your *.o files in a make variable, and use that variable as the target of the run rule, and after the rm command above.
The reason I want you to do this is for debugging purposes. It could be that you have one of the above rules wrong, but since you already built all your .o files once, it is just picking up an old one every time. If you do a make clean before your build, it will catch that.

Resources