Makefile doesn't permit incremental build - c

I have a makefile from an example project, and it unfortunately forces a re-build when any single file in the project changes. I do not have a lot of experience with makefiles, so I'm not sure how to solve this problem.
The makefile defines the files to compile as a single variable SRCS like shown below. Of course, there are about 40 files in this list, in quite a few different directories.
SRCS = \
../../src/file1.c \
../../src/file2.c
Then later it defines the build rules for each .o file generated from each .c file.
$(OBJ_PATH)/%.o: $(SRCS)
$(CC) $(FLAGS) $(filter %/$(subst .o,.c,$(notdir $#)), $(SRCS)) -o $#
According to make running with the -d option, all of the object files must be compiled again when a single .c file changes because $(SRCS) is defined as a dependency above.
How can I change this so if a single file changes only the 1 .o file must be compiled again?

Another solution would be using vpath. Example code:
OBJ_PATH := build
SRCS := \
src/foodir/foo.c \
src/bardir/bar.c
OBJS := $(addprefix $(OBJ_PATH)/,$(notdir $(SRCS:%.c=%.o)))
vpath %.c $(dir $(SRCS))
all: $(OBJS)
$(OBJ_PATH)/%.o: %.c
$(CC) $(FLAGS) $< -o $#

Your recipe was written by somebody knowledgeable about makefiles; it is almost correct. The one correction is, to move the $(filter) statement to the prerequisite line. In this case, that is where it needs to be.
Once it is there, you need to make a few additional adjustments, which you can read about in the manual. So, like this:
PERCENT := %
.SECONDEXPANSION:
$(OBJ_PATH)/%.o: $$(filter $$(PERCENT)/$$(subst .o,.c,$$(notdir $$#)), $(SRCS))
$(CC) $(FLAGS) $< -o $#

Something like this will also work.
SRCS = \
../../src/file1.c \
../../src/file2.c
# Set prerequisites for each output .o file from the matching .c file
$(foreach src,$(SRCS),$(eval $(OBJ_PATH)/$(notdir $(src:.c=.o)): $(src)))
# Create pattern rule with no additional prerequisites.
$(OBJ_PATH)/%.o:
$(CC) $(FLAGS) $< -o $#
So it occurred to me that an, in some senses, even more minimal change would be:
$(OBJ_PATH)/%.o: $(SRCS)
file='$(filter %/$(subst .o,.c,$(notdir $#)), $?)'; [ "$$file" ] && \
$(CC) $(FLAGS) "$$file" -o $#

Usually in a Makefile you do not put the specific .c files as dependencies.
Generally, you list the .o files as dependencies of the main executable.
Make has internal rules for figuring out how to build a .o file from a .c file,
you can override these with your own special rule, or often just changing a few
config variables is sufficient.
A complete tutorial on make is longer than I want to type in this box, but there are plenty of them available with a quick web search.

Related

How to stop Make from recompiling the whole project if one include file changes? [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.

Having trouble placing object files in a new directory using makefile

I am very new at make. Thus far I've managed to create the following using some of GNU manual and tutorials found online. I'd like for make to place all of the created object files into the directory 'obj.' I've been able to successfully create this directory, but I cannot figure out how to place the files in it. Any suggestions or tips are appreciated. Also, on a general note, is there a good source for learning how to work with make besides the GNU documentation?
# specify compiler
CC := gcc
# set compiler flags
CFLAGS := -M -Igen/display -Igen/logic -Iman -Ilib/include -pipe -march=native -ftime-report
# set linker flags
LDFLAGS := -lglut32 -loglx -lopengl32 -Llib
# specify separate directory for objects
OBJDIR := obj
# include all sources
SOURCES := $(wildcard gen/display/*.c gen/logic/*.c man/*.c)
# create objects from the source files
OBJECTS := $(patsubst %.c,%.o,$(SOURCES))
# specify the name and the output directory of executable
EXECUTABLE := win32/demo
# all isn't a real file
all: $(EXECUTABLE)
# compile
%.o: %.c
#mkdir -p $(#D)
$(CC) $(CFLAGS) -c $< -o $(OBJDIR)/$#
# link
$(EXECUTABLE): $(OBJECTS)
$(CC) $^ $(LDFLAGS) -o $#
# clean objects
clean:
#$(RM) -rf $(OBJDIR)
.PHONY: all clean
Any time you see a rule where the output generated does not go to the file $#, you know it's not right. Make will set the $# automatic variable to the file name that it expects to be created and if the recipe does something different, the makefile will not work.
Your rule sends the file to $(OBJDIR)/$#, not $#, so it's not right.
So, you need to write your pattern rule like this:
%.o: %.c
#mkdir -p $(#D)
$(CC) $(CFLAGS) -c $< -o $#
If that doesn't work you'll need to provide more information such as an example of the compile line make invokes, what errors you see, etc.
I've been able to successfully create this directory, but I cannot
figure out how to place the files in it.
There are two parts writing to doing that explicitly.
First, and most fundamental, is that if you want make to create a file, you have to give it a rule for doing so. You do have a pattern rule that could, in principle, have that effect ...
%.o: %.c
# ...
... but in practice, that rule cannot ever be matched to files in the obj/ directory because your sources are not in that directory. This might be more effective:
$(OBJDIR)/%.o: %.c
#mkdir -p $(#D)
$(CC) $(CFLAGS) -c $< -o $#
Note in particular how now the target of the rule matches the artifact actually produced by that rule.
Second, you must have a requirement to build the target of the rule, usually by having it be a dependency of some other rule. Observe that your variable defining the object files contributing to $(EXECUTABLE) does not rely on objects from the obj/ directory. It is generated by this pattern substitution ...
OBJECTS := $(patsubst %.c,%.o,$(SOURCES))
... which generates object names with the same path as the corresponding sources. You probably want something more like this:
OBJECTS := $(patsubst %.c,$(OBJDIR)/%.o,$(SOURCES))
You will note how that also corresponds to the change presented in the previous point.
But that's a lot of work for little gain. You would not have to modify your clean target very much to do without it there. You could write your file in a somewhat simpler and more conventional form and still get output into a separate directory by leveraging the VPATH feature of GNU (and some other) make.

Makefile does not iterate over all the source files?

I want to compile many source file and build a library from them.
My makefile looks approximately like this:
SOURCES := /home/test/src/\*.c
OBJECTS := $(SOURCES:.c=.o)
.PHONY: compileLibrary
compileLibrary:
$(CC) -fPIC -c $(SOURCES) -o $(OBJECTS)
$(CC) -shared -o libshared.so $(OBJECTS)
How ever the process does not iterate over each source file, it seems that makefile does not replace the * in SOURCES by its value.
*.c, on its own, is not expanded, you have to use the wildcard function (like $(wildcard *.c))
It is *.c, not \*.c. \ is escape and removes the special meaning of *.
Obviously your makefile shouldn't contain absolute path. Normally the current directory has to be the one where the makefile is in, so take advantage of it.
You should be actually using the features of make:
libshared.so: $(OBJECTS)
$(CC) -shared -o $# $<
compileLibrary: libshared.so
(note: you can probably do without the compilation rule, because the default is likely good enough)

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.

compile headers dependencies with makefile

I am programming an UDP client server application in the C programming language; I want to automatically compile 2 sources files and 3 header files whenever the dependencies change so I decided to use the make utility.
The makefile target is called "edit" :
edit : server_UDP.o client_UDP.o \
gcc -o edit server_UDP.o client_UDP.o \
client_UDP.o : client_UDP.c cliHeader_UDP.h wrapHeader.h
gcc -c client_UDP.c
server_UDP.o : server_UDP.c servHeader_UDP.h wrapHeader.h
gcc -c server_UDP.c
It doesn't trigger a recompile when I change a few lines of code in wrapHeader.h.
How do to I modify the edit makefile rule(s) when there is a change in wrapHeader.h to recompile server_UDP and client_UDP ?
**note : wrapHeader.h is the main header
cliHeader_UDP.h : include "wrapHeader.h"
servHeader_UDP.h : include "wrapHeader.h"
I think what you want are Make dependency files.
You can specify the compiler to generate a dependency file for you with the '-MMD -MP' arguments, which create a new file with the same name as the source file except with the extension *.d, in the same folder as your source.
The dependency file contains all the headers the code depends on, which will lead to GNU make compiling your source file if a header it uses is modified.
An example dependency file enabled makefile:
# Makefile
CC := gcc
LD := g++
# The output executable.
BIN := program
# Toolchain arguments.
CFLAGS :=
CXXFLAGS := $(CFLAGS)
LDFLAGS :=
# Project sources.
C_SOURCE_FILES := mysourcefile1.c src/myothersrc.c
C_OBJECT_FILES := $(patsubst %.c,%.o,$(C_SOURCE_FILES))
# The dependency file names.
DEPS := $(C_OBJECT_FILES:.o=.d)
all: $(BIN)
clean:
$(RM) $(C_OBJECT_FILES) $(DEPS) $(BIN)
rebuild: clean all
$(BIN): $(C_OBJECT_FILES)
$(LD) $(C_OBJECT_FILES) $(LDFLAGS) -o $#
%.o: %.c
$(CC) -c -MMD -MP $< -o $# $(CFLAGS)
# Let make read the dependency files and handle them.
-include $(DEPS)
This should work for your situation:
SOURCES := server_UDP.c client_UDP.c
OBJECTS := $(patsubst %.c,%.o,$(SOURCES))
DEPS := $(OBJECTS:.o=.d)
edit: $(OBJECTS)
gcc -o edit $(OBJECTS)
%.o: %.c
gcc -c $< -o $#
-include $(DEPS)
You did not say that edit.c includes your two specific headers, but I guess it must, if it links to the objects.
This is exactly the scenario where makepp plays out one of its strengths: If you follow the convention that for every .o file you need to link there is an include statement of a corresponding name (in your case that would be client_UDP.h & server_UDP.h) then makepp will figure everything out itself, besides detecting the header files as dependencies.
This even works recursively, so if you had a wrapHeader.c (where there is no corresponding include statement in edit.c), that would get automatically compiled and linked.
So you don't need a makefile. But if you want to avoid calling makepp edit everytime, then you can create a one-liner
edit:
You will only need to learn make syntax, if you have more complex requirements. But if you do, there is no limit. Besides doing almost all that GNU make can, there are lots more useful things, and you can even extend your makefiles with some Perl programming.

Resources