I am following the manual in order to learn more about Makefiles, so I decided to code along and apply this example ( https://www.gnu.org/software/make/manual/make.html#Letting-make-Deduce-the-Recipes ) to the Makefile of my project.
The problem is that I have a seperate directory for the object files that will be generated, as far as my understanding goes the implicit rules will only look for the corresponding .c files in the same directory as the object file.
My makefile looks like this:
objects = $(addprefix objs/, main.o interface.o \
build.o requests.o parse.o configure.o)
output: $(objects)
gcc -o output $(objects)
objs/main.o: interface.h build.h requests.h parse.h configure.h
objs/interface.o: interface.h
objs/build.o: build.h
objs/requests.o: requests.h
objs/parse.o: parse.h
objs/configure.o: configure.h
.PHONY: clean
clean:
rm output $(objects)
My object files are supposed to go to the objs/ directory the source code files are located in the root directory of the project, like this:
objs/
*.c
*.h
How can I still use implicit rules without having to compile object files into the source file directory?
You just have to define your own implicit rule, since the built-in rules won't do that for you.
Try:
obj/%.o : %.c
$(COMPILE.c) $(OUTPUT_OPTION) $<
Related
I have a directory structure like the following:
Makefile
bin
main.c
Makefile
lib
lib1.c
lib2.c
Makefile
tst
test1.cc
Makefile
In my Makfile I have code the looks like this:
ALL_OBJECTS = main.o lib1.o lib2.o
BINS = binary
binary,SRCS = main.o lib1.o lib2.o
OBJS = $($(*),SRCS)
all: $(ALL_OBJECTS) $(BINS)
%.o : %.c
${CC} -c $^ -o $#
binary:
${CC} -o $# $(OBJS)
My question is when I change and of the source files like main.c, lib1.c or lib2.c the *.o file is re-compiled during make but the binary is not recompiled. How can I ensure that the binary is recompiled when one of its dependencies change?
Some parts of your Makefile don't make much sense to me, and the directory structure you show doesn't really seem to match up well with the Makefile you show. For example, with a directory named lib that contains a Makefile of its own, I'd expect to see that Makefile create a library that depends on lib1.o and lib2.o. Then binary would depend on that library.
But right now, it looks like you're just building binary from a single Makefile, and ignoring the Makefile in the lib directory. That can work too, but it's going to be different from the previous scenario.
For the moment, let's start with a bit "flatter" directory structure, with main.c, lib1.c and lib2.c all contained in a single directory (and the Makefile in that same directory). For this case, we can build the binary with a really simple Makefile:
binary: lib1.o lib2.o main.o
$(CC) -o binary lib1.o lib2.o main.o
We just make that the binary depends on the object files, and how to create the binary from those object files. Any reasonable modern make utility already has built-in rules for how to compile a .c file to produce a .o file, so we don't have to do any more than that unless we want something fairly unusual in how we build those object files.
That does repeat the names of the object files in two places though. We'd usually prefer to avoid that. We can separate out defining the names of the object files from the rule to make the binary from them, to get something more like this:
OBJS = lib1.o lib2.o main.o
binary: $(OBJS)
$(CC) -o binary $(OBJS)
Now we only have the names of the object files in one place, so if (for one obvious example) we add another object file, we only need to add its name in one place, rather than two.
Based on your last comment to #JerryCoffin's answer, you could do something like this:
binary1 : lib1.o lib2.o main1.o
binary2 : lib2.o main2.o
binary3 : lib1.o main3.o
binary1 binary2 binary3:
$(CC) -o $# $^
The first three lines have no recipe, and thus simply are adding prerequisites to the associated binaries. Then you define a recipe for the binary targets using the automatic variable $^, which will expand to that target's dependencies.
I have a C project, which has the following file structure:
Makefile
src
|-utils
| |--vic.c
| |--vic.h
|-mod
| |--type.c
| |--type.h
|-bb.c
|-bb.h
|-main.c
So, at the root directory I have the actual Makefile and the src directory, which includes the source files. Inside the src directory there are multiple .c and .h files along with the main.c file, and there are other directories which also contain other .c and .h files. Please note that the above shown file structure is kept short for brevity. I want to create a Makefile that will automatically compile everything and generate an executable main program, and also delete the object files generated during the compilation. Currently, I have something like this:
CC=gcc
CFLAGS=
RM=rm -rf
OUT=main
SRC=src
OBJ=obj
SOURCES=$(wildcard $(SRC)/*.c)
OBJECTS=$(patsubst $(SRC)/%.c, $(OBJ)/%.o, $(SOURCES))
all: build
build: $(OBJECTS)
$(CC) $(CFLAGS) $^ -o $#
$(RM) $(OBJ)
$(OBJ)/%.o: $(SRC)/%.c
$(CC) $(CFLAGS) -I$(SRC) -c $< -o $#
debug: CFLAGS+=-DDEBUG
debug: build
.PHONY: clean
clean:
$(RM) $(OBJ) $(OUT)
But that doesn't seem to work as expected, as when I issue make command, it returns the following error message:
Assembler messages: Fatal error: can't create obj/main.o: No such file
or directory
Any ideas how to achieve what I want?
It seems you rm -rf obj/ after each step, but there's no mkdir -p obj/ to replace it.
Since GNU make will, itself, remove intermediate targets, I don't see why you would do $(RM) $(OBJ), but your %.o target could have a line like
mkdir -p "$(shell dirname "$#")"
… to ensure that the destination directory exists.
PS: your output is named build rather than main because that's the name you gave it …
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 trying to write a makefile which should pick the sources from src/ and headers from inc/
~/Linuz/src: 1.c, 2.c, 3.c ...
~/Linuz/inc: abc.h, dyz.h
Please help me to create a makefile which should be available at
~/Linuz/some_other_dir/Makefile
PS: Trying to compile it for my linux machine.
Thank you for your suggestions.
all: my_program
%.o: ../src/%.c
$(CC) $(CFLAGS) -I../inc/ -c -o $# $^
my_program: 1.o 2.o 3.o
$(CC) $(LDFLAGS) -o $# $^
clean:
rm -f *.o my_program
If you put your Makefile in the ~/Linuz/some_other_dir/, the following rule
%.o: ../src/%.c
will get the c files from the ../src/ folder (~/Linuz/src/) and create the object (*.o) files in the same folder of the Makefile.
The -I../inc/ option means that the makefile canl get a header files from the ../inc/ folder (~/Linuz/inc/).
The my_program: 1.o 2.o 3.o rule means that the makefile will create the binary in the same directory of Makefile from the object files 1.o and 2.o and 3.o
From the make manual:
$^ The names of all the prerequisites, with spaces between them.
For prerequisites which are archive members, only the member named is
used (see Archives). A target has only one prerequisite on each other
file it depends on, no matter how many times each file is listed as a
prerequisite. So if you list a prerequisite more than once for a
target, the value of $^ contains just one copy of the name. This list
does not contain any of the order-only prerequisites; for those see
the `$|' variable, below.
$# The file name of the target of the rule. If the target is an
archive member, then ‘$#’ is the name of the archive file. In a
pattern rule that has multiple targets (see Introduction to Pattern
Rules), ‘$#’ is the name of whichever target caused the rule's recipe
to be run.
This makefile does not behave as I expect. I want it to build .o files for each .c file in the current directory and subdirectories, and put them in a static library. However, it stops applying my $(INCS) after the first or second file. When it tries to build the second .o file, I don't see the -I paths in the build line and it complains about not finding a header file therein. Names have been genericized to simplify things. I'm using cygwin on Windows XP. I'm using an ARM cross compiler that is not under the cygwin tree. I based this makefile off an answer here. There are only about two dozen .c files so the overhead of creating the dependency files this way isn't a big deal.
# Project specific options
CC = my-cross-gcc
INCS := -I. -Iinc
INCS += -Imy/inc/path
CFLAGS := -Wall -fPIC -static -cross-compiler-specific-options
OUT := bin/libmylib.a
MKDIR:=mkdir -p
### Generic C makefile items below:
# Add .d to Make's recognized suffixes.
SUFFIXES += .d
NODEPS:=clean
#Find all the C files in this directory, recursively
SOURCES:=$(shell find . -name "*.c")
#These are the dependency files
DEPFILES:=$(patsubst %.c,%.d,$(SOURCES))
OBJS:= $(patsubst %.c,%.o,$(SOURCES))
#Don't create dependencies when we're cleaning, for instance
ifeq (0, $(words $(findstring $(MAKECMDGOALS), $(NODEPS))))
-include $(DEPFILES)
endif
#This is the rule for creating the dependency files
%.d: %.c
$(CC) $(INCS) $(CFLAGS) -MM -MT '$(patsubst %.c, %.o,$(patsubst %.c,%.o,$<))' $< > $#
#This rule does the compilation
%.o: %.c %.d %.h
$(CC) $(INCS) $(CFLAGS) -o $# -c $<
# Now create a static library
all: $(OBJS)
#$(MKDIR) bin
ar rcsvq $(OUT) $(OBJS)
clean:
rm -rf $(OBJS) $(OUT) $(DEPFILES)
Why does this makefile not apply $(INCS) when building subsequent .o files? How do I fix it? Output resembles this:
$ make all
my-cross-gcc -I. -Iinc -Imy/inc/path -<compiler options> -o firstfile.o -c firstfile.c
my-cross-gcc -I. -Iinc -Imy/inc/path -<compiler options> -o secondfile.o -c secondfile.c
my-cross-gcc -<compiler flags> -o thirdfile.o -c thirdfile.c
thirdfile.c:23:18: fatal error: myinc.h: No such file or directory
compilation terminated.
When I go to the command line and type in the gcc line to build thirdfile.o and use the -I paths, the object file is successfully built.
There are two different mechanisms for handling header files at work here:
When the compiler is trying to build foo.o from foo.c, and in foo.c it encounters #include "foo.h", it goes looking for foo.h. The -I flags tell it where to look. If it is invoked without the flags it needs to find foo.h, it will complain and die.
When Make is trying to build foo.o, and considering which rule to use, it looks at the prerequisites. The prerequisites for your rule are foo.c foo.d foo.h, so it goes looking for those prerequisites. How is it to know where foo.h is? Note that the compiler flag inside one of its commands is of no use-- it won't make any deductions about that. If it can't find (and doesn't know how to make) a prerequisite, it will reject that rule and look for another one, such as the implicit %.o rule which knows nothing about your $(INCS) variable, and that leads you to the problem described above.
If this is the problem (and you can check by looking at the locations of the headers and doing some experiments) you have a couple of options:
A) You can use the implicit rule, and it's variables. Just add INCS to CFLAGS and you'll probably get the results you want. This tells the compiler what to do, but it still leaves Make in the dark about the dependencies, so you'll probably have to double-check that your dependency handling is correct.
B) You can tell Make where to find the header files:
vpath %.h inc my/inc/path
(You may notice that this is redundant with your INCS variable, and redundancy is bad-- you can eliminate this redundancy, but I urge you to get it working first.)
I'm going to guess that you have files named firstfile.h, secondfile.h, but no file named thirdfile.h?
I would then suppose that make cannot use the rule you gave it because and can't find or build the .h file. So it decides to use the default implicit rule instead.
All I can imagine is that for "thirdfile" your depfile is somehow out-of-date or corrupt. Perhaps it is bad enough that it's confusing make into calling some other default target.