Makefile for multiple files in different directories - c

I am a newbie in creating makefiles, and would be glad if someone could help me.
I have created several header files (for function declarations) and corresponding .c programs (8 in total), for the function definitions (including the main function). These are listed in the .../include/ directory. Additionally, I have created another directory for the storing the output files : .../bin/ after compilation. I tried to link the .o files, but was unsuccessful. I have attached a small piece of the makefile code (similar one taken from the internet) :
CC = g++
CFLAGS = -Wall -O3
INC_DIR := /media/sf_~share/151*/Codes/include
OBJ_DIR := /media/sf_~share/151*/Codes/obj
INC_FILES := $(wildcard $(INC_DIR)/%.c)
OBJ_FILES := $(patsubst $(INC_DIR)/%.c, $(OBJ_DIR)/%.o, $(INC_FILES))
all : $(APP)
$(APP) : $(OBJ_FILES)
$(CC) $(CFLAGS) -o $# $^
$(OBJ_DIR)/%.o : $(INC_DIR)/%.c
$(CC) $(CFLAGS) -o $# $<
clean:
rm -f *.o $(APP)
I would be glad if someone could either suggest me a different code, or rectify this as it is.

There are a few mistakes in your Makefile:
Wildcard usage
You should use *.c rather than %.c for wildcard expansion, like this:
INC_FILES := $(wildcard $(INC_DIR)/*.c)
Patsubst usage
You don't need to specify the full pattern $(INC_DIR)/%.c for patsubst, instead, simply use:
OBJ_FILES := $(patsubst %.c, %.o, $(INC_FILES))
Missing $(APP) value
I don't know if you simply forgot to add this to the sample or not, but since $(APP) is an empty string, the makefile says:
make: Nothing to be done for `all'.
Adding APP := program triggers a build for all the *.c files in include.

Related

How to build multiple targets with similar name?

So I have the exact same question as the one below, but no one has answered it.
Pattern matching Makefile with multiple executable targets
I am trying to build a series of small test files each have a pattern of "test*.c" to test my library.
I wanted to write a makefile that builds executables for every one of the test files all at once (each name: test1, test2, test3..etc.). However, I am not sure how to achieve that.
What I have so far is the following:
SRC := $(shell find *.c)
ALL_PROG := $(patsubst %.c, %, *.c)
.PHONY: all
all: $(ALL_PROG)
$(ALL_PROG): $(SRC)
-gcc $< -o $#
This is a bad attempt because the targets take all .c files as dependency, which caused circular dependency.
Using shell script can get the job done very easily, but I am wondering if there's a way to do the same job.
Thanks in advance.
Use $(ALL_PROG): %: %.c instead of $(ALL_PROG): $(SRC).
Here is an example Makefile I might use with GNU make:
CC := gcc
CFLAGS := -Wall -O2
LDFLAGS := -lm
PROGS := $(patsubst %.c, %, $(wildcard *.c))
.PHONY: all clean test $(patsubst %, test#%, $(PROGS))
all: $(PROGS)
clean:
rm -f $(PROGS)
$(PROGS): %: %.c
$(CC) $(CFLAGS) $^ $(LDFLAGS) -o $#
$(patsubst %, test#%, $(PROGS)): test#%: %
./$^
test: $(patsubst %, test#%, $(PROGS))
As usual, note that the indentation should use a Tab rather than spaces; the editor used here on stackoverflow.com auto-converts them to spaces.
The PROGS variable will contain the names of all *.c files in the directory.
The .PHONY: directive tells Make which targets do not refer to actual files. The $(patsubst %, test#%, $(PROGS)) expands to the list of executable names, with each name prepended with test#: if the directory contains files foo.c and bar.c, this expands to test#foo test#bar.
The $(PROGS): %: %.c recipe compiles each .c file to the corresponding binary.
The $(patsubst %, test#%, $(PROGS)): test#%: % recipe creates a test target for each binary. If we have files foo.c and bar.c, then this rule expands to test#foo test#bar: test#%: %. This means that for both test#foo and test#bar targets, the corresponding test#% target requires the % binary. The ./$^ in turn expands to ./%, and thus the binary name. (If you don't want Make to show the command being run, use #./$^. If you don't care if a test fails, use -./$^.)
The test recipe expands to test#foo test#bar if we have foo.c and bar.c; i.e. all possible test targets.
You can run make clean test to recompile all .c files in the directory, and execute them.
If you are only worried about a specific test program, say foo.c, you can run make test#foo, which will recompile the program if foo.c is newer than foo.
You can do that. I am updating a simple make file which builds multiple targets. You can modify it as your requirement.
TEST1 = test1.exe
TEST2 = test2.exe
### Executable Program Files ###
all : $(TEST1) $(TEST2)
$(TEST1) : test1.c
gcc -o $(TEST1) test1.c
$(TEST2) : test2.c
gcc -o $(TEST2) test2.c

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 doesn't permit incremental build

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.

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.

GNU Make with several folders and files

I have to write a "good" makefile for a program that has several folders:
bin, inc, obj, src. Here are my make files. If I type make it just says that nothing can be done although the program is not compiled at all. Guess I have a error somewhere but I really can't find it. (ps I'm quite new to make).
Thanks a lot for your help!
makefile in bin folder:
vpath %.o ../obj/
$(prog): $(objs)
$(cc) $(ccflags) -o $# $^ $(ldflags)
makefile in obj folder:
vpath %.c ../src
vpath %.h ../inc
all: $(objs)
%.o: %.c %.h
$(cc) $(ccflags) -c $<
-include *.d
general makefile:
export prog := inv_svn
export objs := $(patsubst %.c, %.o, $(wildcard src/*.c)))
export src_dir := src
export inc_dir := inc
export obj_dir := obj
export bin_dir := bin
export cc := gcc
export ccflags := -I $(PWD)/$(inc_dir) -MMD -g -Wall
export ldflags := -lcurses -lgdbm
test := ./$(prog)
all: $(prog)
$(prog): $(bin_dir)
$(bin_dir): $(obj_dir)
$(bin_dir):
make -C $#
$(obj_dir):
make -C $#
.PHONY: clean
clean:
rm -f $(obj_dir)/*.[od]$(prog)
There are too many problems here to fix all at once. Let's start small and simple, and build up.
First, you're using Make recursively when you really don't have to. Later, you should reconsider this design. For now, let's see if we can get obj/makefile working.
Second, the sub-makefiles depend on variables (like objs) passed down from the invoking makefile, variables which they could just as well construct themselves. This is bad design. We'll put the assignment in obj/makefile:
objs := $(patsubst %.c, %.o, $(wildcard ../src/*.c))
(Note that I've removed an extra ) that was messing things up.)
Third, when we test this, we get ../src/foo.o ../src/bar.o, which is probably not what we want; we want to build the objects in obj/, not src/ (the assignment in the main makefile had the same problem). So we change it:
objs := $(patsubst ../src/%.c, %.o, $(wildcard ../src/*.c))
(There are more graceful ways, but never mind that for now.)
Fourth, I trust you can make similar changes to bin/makefile.
Fifth, in the main Makefile, you treat the subdirectories as targets, when they really aren't; the point of those rules isn't to construct the subdirectories, but to run Make in them. If they already exist (which they do), Make is satisfied, and concludes that $(prog) and all need not be rebuilt. We can solve this with some PHONY targets:
.PHONY: RUN_IN_$(obj_dir) RUN_IN_$(bin_dir)
$(prog): RUN_IN_$(bin_dir)
RUN_IN_$(bin_dir): RUN_IN_$(obj_dir)
RUN_IN_$(bin_dir):
make -C $(bin_dir)
RUN_IN_$(obj_dir):
make -C $(obj_dir)
Crude but effective.
That should be enough to get you off the ground.

Resources