Let's say I have a C project. There are several files:
/myproject/makefile
/myproject/src
/myproject/build
/myproject/src/baseHeader.h
/myproject/src/module1/module1.h
/myproject/src/module1/module1_a.c
/myproject/src/module1/module1_b.c
/myproject/src/main.c
I want make to search in src for all *.h files which are not on the first depth level i.e. make should look for *.h files in
/myproject/src/module1/
so it will not use
/myproject/src/baseHeader.h
Then for every found .h make should create target with the basename of .h i.e. for
/myproject/src/module1/module1.h
it should be
./build/module1.o: ./src/module1/module1_a.c ./src/module1/module1_b.c ./src/module1/module1.h $(OTHER_DEPS) | $(OPTIONAL_DEPS)
$(CC) -c $< -o $#
also it should create target for every .c file in /myproject/src/ dir without going recursive in this example only main.c will be found and target should look like
./build/main.o: ./src/main.c $(OTHER_DEPS) | $(OPTIONAL_DEPS)
How this can be done?
Could someone provide me with the link to example if exists?
I'm asking for this because after a day of trying I think it's better to forget about make and use bash scripts instead...
This can be done but it is not trivial. One way to do it is to build a list of all of the .h files recursively in the src directory and its subdirectories, then remove from that list the .h files in the src directory.
We can search the src directory and all subdirectories for .h files with $(wildcard src/**/*.h)) and only the src directory for .h files with $(wildcard src/*.h). These can be combined with the filter-out function to produce a list containing only the .h files in subdirectories of src/ like
MODULES := $(filter-out $(wildcard src/*.h),$(wildcard src/**/*.h))
This will produce a list like
/myproject/src/module1/module1.h
/myproject/src/module2/module2.h
/myproject/src/module3/module3.h
We could remove the directory structure with
INCLUDES := $(notdir MODULES)
which will produce
module1.h
module2.h
module3.h
We can convert these into object files for the modules with
OBJDIR = build
OBJS := $(addprefix $(OBJDIR)/, $(patsubst %.h,%.o, $(INCLUDES)))
Then we define an empty target rule to create all these
.PHONY: modules
modules: $(OBJS)
And the implicit rule to create the objects
$(OBJDIR)/%.o: $(dir $(findstring %.h, $MODULES))*.c %.h $(OTHER_DEPS) | $(OPTIONAL_DEPS)
$(CC) -c $? -o $#
EDIT: Its not particularly advisable to use wildcards in prerequisite lists but it is the best solution I have for now.
To compile a target for every .c file in src without searching recursively we take a similar approach starting off.
SRCS := $(wildcard src/*.c)
will find all out the .c files in the top level src directory. We can compile targets for these with
$(SRCS:%.c=$(OBJDIR)/%.o): %.c $(OTHER_DEPS) | $(OPTIONAL_DEPS)
Related
My project has a directory called tests/ which contains an arbitrary number of C source files, each one is a self-contained program designed to test a library. For each of these sourcefiles, I want to create an executable of the same name in my build/ directory.
E.g. tests/test_init.c would compile to an executable file build/test_init.
Currently, my Makefile snippet looks like the following:
BUILD_DIR = build
TEST_DIR = tests
test_sources:= $(TEST_DIR)/*.c
test_executables:= $(patsubst %.c, %, $(test_sources))
.PHONY: tests
tests: $(test_executables)
$(CC) $^ -o $# -g
But this fails to produce to desired result. Any help would be much appreciated.
First you need the wildcard function to find the sources:
test_sources:= $(wildcard $(TEST_DIR)/*.c)
Then the correct names for the executables:
test_executables:= $(patsubst $(TEST_DIR)/%.c, $(BUILD_DIR)/%, $(test_sources))
Then a pattern rule to build a test executable from the corresponding source:
$(BUILD_DIR)/%: $(TEST_DIR)/%.c
$(CC) $< -o $# -g
(A static pattern rule might be a little tidier, but it's a more advanced method.)
Finally a phony target to build all of the tests:
.PHONY: tests
tests: $(test_executables)
If you wanted Make to run all of these tests, you could make a phony pattern rule run_test_%, but that can wait for another day.
This Makefile will detect all files in test/*.c and provides tasks build_tests, run_tests, and clean_tests.
all: build_tests
define test_template
build_tests: test/$(1)
run_tests: build_tests run_test_$(1)
test/$(1) : test/$(1).c
$$(CC) $$^ -o $$#
.PHONY : run_test_$(1)
run_test_$(1) : test/$(1)
test/$(1)
endef
clean: clean_tests
clean_tests:
rm -fv $(foreach test, $(tests),test/$(test))
# Auto detect the tests (any .c file in the test directory),
# and store the list of tests names.
tests := $(foreach test, $(wildcard test/*.c),$(patsubst %.c,%,$(notdir $(test))))
# Add information about each test to the Makefile.
$(foreach test, $(tests), $(eval $(call test_template,$(test))))
Note: I'm not sure how to get tabs working inside a code block in markdown, so you'll need to replace spaces with a single tab on each indented line if you copy and paste this.
I have a project that includes many source files in different folder locations. For some reason my Makefile can either do one of the following but not both at the same time (which is what I really want):-
1) Compile all files into a separate directory
2) Perform the compilation ONCE, gcc needs to be called once only as this significantly reduces the compilation time.
This is a code snippet that works to achieve option 1:-
INCLDDIRS := "The needed include directories"
CFLAGS = "some c flags"
C_SOURCE = "Many many source files in different directories"
C_SOURCE_NAMES = $(notdir $(C_SOURCE))
OBJECT_DIRECTORY = ObjDir
C_OBJECTS = $(addprefix $(OBJECT_DIRECTORY)/, $(C_SOURCE_NAMES:.c=.o) )
all: $(OBJECT_DIRECTORY) $(C_OBJECTS)
$(OBJECT_DIRECTORY):
mkdir ObjDir
$(OBJECT_DIRECTORY)/%.o:%.c
$(CC) $(CFLAGS) $(INCLDDIRS) -c -o $# $<
For some reason the above compiles each c source file individually and generates an object file (i.e. gcc is called for all source files). Which is not what I want. However, at least all generated files are located in ObjDir
and this is the code snippet that works to achieve option 2:-
INCLDDIRS := "The needed iclude directories"
CFLAGS = "some c flags"
C_SOURCE = "Many many source files in different directories"
C_SOURCE_NAMES = $(notdir $(C_SOURCE))
OBJECT_DIRECTORY = ObjDir
C_OBJECTS = $(OBJECT_DIRECTORY)/*.o
all: $(OBJECT_DIRECTORY) $(C_OBJECTS)
$(OBJECT_DIRECTORY):
mkdir ObjDir
$(C_OBJECTS): (C_SOURCE)
$(CC) $(CFLAGS) $(INCLDDIRS) -c $(C_SOURCE)
For the above snippet, all files are compiled once (i.e. gcc is called only once) but the object files are generated at the same location as the Makefile and not into a separate directory. I do not want to mv the files after they are generated as this is not the cleaner solution.
My Question is:
What do I have to do to my Makefile so that compilation is performed once and that the object files are generated into a separate directory?
The makefile you want will look something like this.
INCLDDIRS := "The needed include directories"
CFLAGS = "some c flags"
C_SOURCE = "Many many source files in different directories"
C_SOURCE_NAMES = $(notdir $(C_SOURCE))
OBJECT_DIRECTORY = ObjDir
BINARY := your_binary
all: $(BINARY)
$(OBJECT_DIRECTORY):
mkdir $#
$(OBJECT_DIRECTORY/$(BINARY): $(C_SOURCE) | $(OBJECT_DIRECTORY)
$(CC) $(CFLAGS) $(INCLDDIRS) -o $# $^
It uses an order-only prerequisite for the output directory (so make knows to create it first but not count it as causing a rebuild).
It lists the source files as the prerequisites of the output binary and uses them all on the compilation line.
The main problem with this makefile, and with your goal, is that a change to any source file will cause every source file to be recompiled from scratch. That's fairly inefficient as far as incremental work goes. (That's why the default idea is to use intermediate object files. You trade some from-clean speed off against incremental speed.)
The reason your second makefile didn't work correctly is that, in a clean directory, the C_OBJECTS variable has no value. Your wildcard $(OBJECT_DIRECTORY)/*.o matches nothing.
That said it was also incorrect in that it listed every source file as a prerequisite for every object file which isn't at all correct.
This question already has answers here:
Building multiple executables with similar rules
(5 answers)
Closed 9 years ago.
I am having a directory called test where make file should be. i am having subdirectory called sub1, sub2, sub3.
test/Makefile
test/sub1
test/sub2
test/sub3
I want to create exe1 by compiling sub1, exe2 by compiling sub2 and exe3 from sub3.
Can i add more than one directory in vpath?? or any other solution
You could simply have a very simple makefile in the test directory, just going into the subdirectories and calling makefiles in them. The subdirectories have makefiles that builds normally, but simply put the executable in the parent directory.
First of all: Yes you could add more than one directory in vpath. Each entry is separated with a colon ':'
vpath %.c test/sub1:test/sub2:test/sub3
But you'll getting into trouble as soon you have the same filename (with different content) in two directories. Consider:
test/Makefile
test/sub1/main.c
test/sub1/foo.c
test/sub1/bar.c
...
test/sub2/main.c
test/sub2/blish.c
test/sub3/blash.c
...
test/sub3/main.c
test/sub3/okEnoughForNow.c
And your makefile containing:
vpath %.c sub1:sub2:sub3
exe1.exe : main.c foo.c bar.c
gcc -o $# $^
exe2.exe : main.c blish.c blash.c
gcc -o $# $^
exe3.exe : main.c okEnoughForNow.c
gcc -o $# $^
The result would be:
gcc -o exe1.exe sub1/main.c sub1/foo.c sub1/bar.c
gcc -o exe2.exe sub1/main.c sub2/blish.c sub2/blash.c
gcc -o exe3.exe sub1/main.c sub3/okEnoughForNow.c
As you can see, all exe's contain sub1/main.c as this is the main.c found first; Its path appears first on the vpath.
Joachim's Approach is definitive a simple, and very common solution. I would choose it as well if the programs in your subfolders are completely unrelated: You could have in each directory a makefile containing something like:
SRC := $(wildcard *.c)
%.exe : $(SRC)
gcc -o $# $^
Assuming, all .c files in each of your sub* shall be part of your program, and there are no subfolders in your sub's. Otherwise you'll need a different approach to scan your .c files, or specify them individually.
In your main makefile you can run for each subfolder a new instance of make, using those makefiles. Which gives you a main Makefile like:
# Get all subfolders name without trailing slash
PROGS := $(patsubst %/,%,$(wildcard */))
# Each subfolder can be made by calling make in
# that folder. A file prog.exe is created.
.PHONY : $(PROGS)
$(PROGS) :
$(MAKE) -C $# prog.exe
# Now every .exe depends on its subfolder, calls
# Make there - see rule above and copies the
# prog.exe from there into the root, with the name
# of the subfolder. (Alternatively you could use
# mv instead of cp)
%.exe : %
cp $</prog.exe $#
Assuming the name of your .exe is the same as the directory name and all subfolders are containing programs.
However, calling make from a running make instance (recursive make) can cause a real headache as soon as there are any dependencies between the generated files of the subfolders.
Another solution:
A different approach whithout using recursive make is having rules dynamically created. In that case your main Makefile could look like this. (I'm again assuming all subfolders are containing programs, all subfolders are flat, and all .c files in those subfolders are part of your program) This has the advantage that you'll have to maintain just one makefile, and there can be any dependency between the different programs. But still it has the disadvantage that you cannot manage your different programs seperately.
That's the complete makefile:
%.exe :
gcc -o $# $^
PROGS := $(patsubst %/,%,$(wildcard */))
$(foreach P,$(PROGS),$(eval OBJ_$(P) := $(wildcard $(P)/*.c)))
$(foreach P,$(PROGS),$(eval $(P).exe : $(OBJ_$(P))))
.PHONY : all
all : $(addsuffix .exe,$(PROGS)
We're starting with a rule for compiling: Any .exe is generated by invoking gcc having all prerequisites as source files.
%.exe :
gcc -o $# $^
Then, next step is to obtain all "programs" by scanning for all subfolders and stripping off the trailing slash
PROGS := $(patsubst %/,%,$(wildcard */))
The next step is to create for each program a variable containig all Sources. Note the eval function expands, and passes everything to make as it has been written in the Makefile.
$(foreach P,$(PROGS),$(eval SRC_$(P) := $(wildcard $(P)/*.c)))
Thus the line above, with your sub1, sub2 and sub3 will become:
SRC_sub1 := $(wildcard sub1/*.c)
SRC_sub2 := $(wildcard sub2/*.c)
SRC_sub3 := $(wildcard sub3/*.c)
The eval function can even be used to create rules:
$(foreach P,$(PROGS),$(eval $(P).exe : $(SRC_$(P))))
So this will expand to (assuming the file structure in the example above)
sub1.exe : sub1/main.c sub1/foo.c sub1/bar.c
sub2.exe : sub2/main.c sub2/blish.c sub2/blash.c
sub3.exe : sub3/main.c sub3/okEnoughForNow.c
Now we have three rules without a recipe. Make says "if you have a rule without recipe, and an implicit rule that matches can be found, this rule is used with the prerequisites added from the rule that does not have the recipe" Thus, for those 3 rules the implicit rule of %.exe above applies.
Basically that's the trick. For your convenience you can add
.PHONY : all
all : $(addsuffix .exe,$(PROGS))
So make all makes everything.
Extension:
If you'd like to be able to make the .o files seperately as well, you could add one more implicit rule like:
%.o : %.c
gcc -c -o $# $<
and make your programs dependent on the .o rather than on the .c files:
$(foreach P,$(PROGS),$(eval OBJ_$(P) := $(patsubst %.c,%.o,$(wildcard $(P)/*.c))))
$(foreach P,$(PROGS),$(eval $(P).exe : $(OBJ_$(P))))
Then you'll have your .exe dependend on the .o that can be found by changing .c into .o after scanning all sources. Via the implicit rule chain %.o : %.c make will know what to do.
I am working on a C project which contains around 200 .c files and some .h files. Not all of these 200 files are required in the final product. Currently around 180 files needs to be compiled. We have a file "compile_only_these.c" which includes these 180 *.c files required for the project. Our makefile compiles only this file instead of individual .c files.
/* file: compile_only_these.c*/
#include "file1.c"
#include "file2.c"
.
.
.
#include "file180.c"
But I think including .c files is a bad idea. Because every time I modify any of these files, all files are compiled again.
Can you suggest a better way to compile these files.
More info:
All .c files are in same folder "../project/src"
I keep adding new .c files which are required to be compiled. I dont want to modify Makefile every-time I add a new file.
I still want to keep those 20 .c files which I am not compiling right now. I may use it in future. Deleting these files are moving them to other directory is not a solution
What you need is a variable in the makefile, a list of required object files, like this:
OBJS := file1.o file2.o ... file180.o
You can have Make construct it from the compile_only_these.c file like this:
OBJS := $(shell sed -e '/\#include/!d' -e 's/\#include "\(.*\)\.c"/\1.o/' compile_only_these.c)
Do you also need a hand with the rule that uses these objects to construct the final product?
As already mentioned, it's sort of a weird way to manage a project, but given what you have to work with, you might try something along this approach...
CC = gcc
OBJFILE = myprog
# Tweak to match whatever you compile with normally
CFLAGS = -O2 -Wall -std=c89 -pedantic
LDFLAGS= # Extra flags here, for example -lm -pthread
RM = rm -f
SRCS = $(wildcard *.c)
OBJS = $(SRCS:.c=.o)
$(OBJFILE):$(OBJS)
$(CC) -o $# $^ $(LDFLAGS)
clean:
$(RM) core *~ $(OBJS) $(OBJFILE)
You will obviously need to adjust the path(s) for the specifics of your build hierarchy if you want to do more in your make than just compile this list of files, but this is a general approach for grabbing all files with wildcard substitution.
I am trying to write a makefile for a small scale application I wrote in C under Linux. Currently all my source files .c are in the top level directory and all header files in
an include directory. Here is the makefile I used for this.
IDIR =include
CC=gcc
CFLAGS=-I$(IDIR)
ODIR=obj
_OBJ = main.o kernel.o user_app.o myargs.o ofp_msgs.o pkt_ip.o pkt_ether.o pkt_tcp.o pkt_udp.o pkt_icmp.o
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
#DEPS = ofp_msgs.h
$(ODIR)/%.o: %.c
$(CC) -c -o $# $< $(CFLAGS)
all: jam
jam: $(OBJ)
gcc -o $# $^ $(CFLAGS) -lpthread
.PHONY: clean
clean:
rm -f $(ODIR)/*.o *~ jam
It works fine but what I want is that for example I make a sub directory called "Packet" and all my packet parsing files i-e "pkt_ip.c, pkt_tcp.c etc" should be in that directory where as their header files should still be in the top level directory i-t "toplevel/include". I did a bit of search and the most common way was to use recursive make. Then I see a lots of pages complaining about recursive make. Can anyone please help me in this as how to do this right ?
Thanks
I recommend checking out the method described in Recursive Make Considered Harmful.
I have used it on several projects (small to medium-size), and find it simpler to use, and easier to wrap ones head around, than the recursive approach.
Basically, you have a Makefile in the root directory which includes a (partial) makefile from each of the subdirectories:
SRC := main.c
MODULES := Packet lib etc
-include $(patsubst %, %/module.mk, $(MODULES))
OBJ := $(patsubst %.c, %.o, $(filter %.c,$(SRC)))
# (...)
Packet/module.mk:
SRC += Packet/pkt_ip.c Packet/pkt_tcp.c
LIBS += -lsome_library
These module makefiles can of course also define their own module targets, or special build requirements.
Unlike recursive make, "make" will only be invoked once, which for most use cases will lead to a faster build.
However, for most smaller projects neither build time nor complexity will be a major concern, so use what feels most natural.
there are several ways to do this but you can certainly use VPATH:=Packet to tell make to look for source files inside the 'Packet' directory. see make manual