Why is my makefile recompiling even if I just compiled the source? - c

I have a simple makefile that compiles a p.c file to an executable using gcc on Linux.
The p.c file depends on a a.h file.
My makefile looks like this:
//makefile
CC = gcc
build: p.c a.h
$(CC) -o out p.c
clean:
rm -f *.exe
rebuild: clean build

Your makefile doesn't produce the files it promises to produce, namely build, clean and rebuild. Since these targets are not files they should be marked as phony targets:
.PHONY: build clean rebuild
build target should be:
build : out
out : p.c a.h
$(CC) -o $# p.c

This part
build: p.c a.h
$(CC) -o out p.c
says "I'm compiling with $(CC) -o out p.c and the result will be a file named 'build'". Since you lied to make (this creates the out file instead), it will try building 'build' again.
There's a lesson for Makefile writers here: always use the $# variable (denoting the target) to avoid this error:
out: p.c a.h
$(CC) -o $# p.c
For more advice, see Paul's Rules for Makefiles.

Learner, here is an example of using a variable to store the name of the executable. This way you only need to specify it in one place at the start of your Makefile:
EXECUTABLE = out
.PHONY: build clean rebuild
build: $(EXECUTABLE)
$(EXECUTABLE): p.c a.h
$(CC) -o $# p.c
clean:
rm -f $(EXECUTABLE)
rebuild: clean build
Normally you would also have your .c and .h files listed in variables too so that you can add/remove files from your build easily without having to search through your Makefile for all of the places that they are used.

Makefiles have the general syntax:
target : dependencies
commands to make target from dependencies
So your Makefile expects to make a file called build using the build : p.c a.h target.
Since the commands don't actually make this file each time you call make it's having to redo the command.
(PS: Linux binaries don't have a .exe extension)

If you want to avoid always recompiling the source, then your target should depend on the object file, not the source file:
target.exe : p.o
$(CC) -o $# $?;
p.o: p.c a.h
$(CC) -c $# $?;
A typical makefile doesn't usually have an explicit rule per object file, nor does it usually list explicit dependencies between implementation and header files; you usually see an implicit rule like
%.o : %.c
$(CC) -c $(CFLAGS) $?;
(where $? indicates the list of prerequisites for that target) or, if your project is dead simple (one source file), you don't even need that; you can usually get away with
all: target
target: target.o
assuming you have a file named target.c, the above will build target using the default compiler and CFLAGS options.
Likewise, a typical makefile (at least in my experience) doesn't explicitly list header dependencies; rather, it relies on a compiler option to generate those dependency lists automagically (for gcc, that option is -M). See here for an example.

I have understood that it is necessary for the 'target' and 'output file' names to match fully for the make to be able to recognize if recompilation is not required. So in case of Windows environment (as make I have tried mingw32-make.exe) it should be like this:
build.exe: p.c a.h
gcc -o build.exe p.c
or
build.exe: p.c a.h
gcc -o build p.c # .exe is added automatically to generated file
This code will lead to recompilation always when make is called:
build: p.c a.h
gcc -o build p.c # target is "build" and it is not the same as "build.exe" which is the output of compilation

Related

Using makefile with multiple C programs

I've written multiple C programs in different files and I want to run all three of them in the same time, on the same argv:
That's what I tried so far but its only running the last program digcmp.c:
CC=gcc
a_OBJS=lexcmp.o
b_OBJS=lencmp.o
c_OBJS=digcmp.o
EXEC=lex len dig
DEBUG = -g
CFLAGS = -std=c99 -Wall -Werror $(DEBUG) #if you have CFLAGS you do not have to write for each file $(CC) -c $*.c!!!
lex: $(b_OBJS)
$(CC) $(a_OBJS) -o $#
len: $(b_OBJS)
$(CC) $(b_OBJS) -o $#
dig: $(c_OBJS)
$(CC) $(c_OBJS) -o $#
lexcmp.o: lexcmp.c
lencmp.o: lencmp.c
digcmp.o: digcmp.c
clean:
rm -f lex $(a_OBJS)
rm -f len $(b_OBJS)
rm -f dig $(c_OBJS)
The make program have many implicit rules. In fact they are what makes your lexcmp.o: lexcmp.c (etc.) rules work.
All you need is to list the rules to make the executable programs themselves:
lexcmp: lexcmp.o
lencmp: lencmp.o
digcmp: digcmp.o
The above is a perfectly fine Makefile on its own, and if you run e.g.
$ make lencmp
then the lencmp.c source file will be built into the object file lencmp.o which will then be linked into the executable lencmp program.
If you want specific compilation flags when building just set the CFLAGS variable and it will be used automatically. I also recommend a default target which might list all executable targets as dependencies to build all of them:
CFLAGS = -Wall -Wextra
.PHONY: all
all: lexcmp lencmp digcmp
This should really be enough to build all your executable files (skipping the object-file intermediate stage) with the flags you want.
The .PHONY target tells make that it's not supposed to generate a file with the name all.

C actualize files through makefile all at once

I am working on project, where i use couple of .c and .h files.
I created Makefile where i actualize executable program based on changes in all of these files.
Problem is, when i use make, program is compiled, but when i execute program, it runs without any change. I need to save ( working in vim so :w ) all included files, even when i changed only one.
If i don't save all these files, program is compiled, but executes the same thing as it did before change.
Could someone explain me why is that ?
Makefile code :
CC=gcc
CFLAGS=-WALL
execFile: execFile.o functions.h newDataTypes.h
Thank you.
The reason you are not getting execFile updated is because you're NOT updating it. Or at least you don't seem to be in this particular case.
There are many ways to get about doing this. However since you are using gcc and I assume you're using gnu make the following is probably the best solution you can execute1.
Given the files:
-rw-r--r-- 1 user sudo 73 Nov 4 22:54 exeFile.c
-rw-r--r-- 1 user sudo 74 Nov 4 22:54 exeFile.h
-rw-r--r-- 1 user sudo 90 Nov 4 22:55 hello_world.c
-rw-r--r-- 1 user sudo 888 Nov 4 23:03 Makefile
cat exeFile.c
#include <stdio.h>
#include "exeFile.h"
int main()
{
hello_world();
}
exeFile.h
#ifndef _EXEFILE_H
#define _EXEFILE_H
extern void hello_world();
#endif
hello_world.c
#include <stdio.h>
#include "exeFile.h"
void hello_world()
{
printf("Hello World\n");
}
you can set up a make file that generates dependencies and ensures that the program will always be compiled correctly:
CC=gcc
CFLAGS=-Wall
SOURCES=exeFile.c hello_world.c
EXE=exeFile
OBJ=$(SOURCES:%.c=%.o)
DEPDIR := .deps
$(shell mkdir -p $(DEPDIR) >/dev/null)
DEPFLAGS = -MT $# -MMD -MP -MF $(DEPDIR)/$*.Td
COMPILE.c = $(CC) $(DEPFLAGS) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
COMPILE.cc = $(CXX) $(DEPFLAGS) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
POSTCOMPILE = #mv -f $(DEPDIR)/$*.Td $(DEPDIR)/$*.d && touch $#
%.o: %.c
%.o: %.c $(DEPDIR)/%.d
$(COMPILE.c) $(OUTPUT_OPTION) $<
$(POSTCOMPILE)
%.o : %.cc
%.o : %.cc $(DEPDIR)/%.d
$(COMPILE.cc) $(OUTPUT_OPTION) $<
$(POSTCOMPILE)
%.o : %.cxx
%.o : %.cxx $(DEPDIR)/%.d
$(COMPILE.cc) $(OUTPUT_OPTION) $<
$(POSTCOMPILE)
$(DEPDIR)/%.d: ;
.PRECIOUS: $(DEPDIR)/%.d
$(EXE): $(OBJ)
$(CC) -o $# $(OBJ) $(LDFLAGS)
clean:
$(RM) $(OBJ) $(EXE)
dev-clean: clean
$(RM) -r $(DEPDIR)
include $(wildcard $(patsubst %,$(DEPDIR)/%.d,$(basename $(SOURCES))))
Let's go over the relevant parts about dependencies
DEPDIR =
This implementation places dependency files into a subdirectory named .deps .
$(shell mkdir -p $(DEPDIR) 2>/dev/null)
GCC does not create subdirectories for output, this line ensures that the DEPDIR directory always exists.
DEPFLAGS = ...
These are GCC-specific flags which tell the compiler to generate dependency info.
-MT $#
Set the name of the target in the generated dependency file.
-MMD
Generate dependency information in addition to compiling. -MMD omits system headers from the generated dependencies: if you prefer to preserve system headers as prerequisites, use -MD instead.
-MP
Adds a make target for each prerequisite in the list, this avoids errors when deleting files.
-MF $(DEPDIR)/$*.Td
Write the generated dependency file to a temporary file $(DEPDIR)/$*.Td e.g. hello_world.c will generate hello_world.Td as temp dependency content for use in Makefile.
POSTCOMPILE = ...
First rename the generated temporary dependency file to the real dependency file. We do this in a separate step to side-step compile errors. Next we explicitly touch the files to avoid a gcc bug.
%.o : %.c
Delete the built-in rules for building object files from .c files, so that our rule is used instead. Do the same for the other built-in rules.
... $(DEPDIR)/%.d
Declare the generated dependency file as a prerequisite of the target, so that if it’s missing the target will be rebuilt.
$(DEPDIR)/%.d: ;
Create a pattern rule with an empty recipe, so that make won’t fail if the dependency file doesn’t exist.
.PRECIOUS: $(DEPDIR)/%.d
Mark the dependency files precious to make, so they won’t be automatically deleted as intermediate files.
include ...
Include the dependency files that exist: translate each file listed in SOURCES into its dependency file. Use wildcard to avoid failing on non-existent files.
1 See Auto-Dependencies Generation for details.
Fix:
Tell make that the executable depends only on the object file and the object file depends on the header files:
execFile: execFile.o
execFile.o: functions.h newDataTypes.h
Explanation:
In order to build your executable two steps are needed:
compilation of C source files (that include header files) to produce object files,
linking of the object files to produce the executable.
So, when changing your header files you must re-compile, that is re-built the object files, not just re-link that would produce the same executable from the same object files.
In your Makefile the dependencies are not properly defined. You did not tell make that the object file (execFile.o) shall be rebuilt when your header files change. Instead, you told it that the executable (execFile) shall be rebuilt.
First of all, your dependencies are mistaken. Your executable does not depend on the .h header files, as they are using only at compilation time. The dependencies are normally between .o files and .h files, as when you modify one .h file, the including .c file must be compiled to generate the .o file. so in case you have execFile.o (which, on lack of complete information, I'll suppose it depends on execFile.c, which #includes functions.h and newDataTypes.h, the rule should be:
execFile.o: execFile.c functions.h newDataTypes.h
As it has been pointed out in other responses, there's no need to write the command to build the .o file, as there is a default rule like this:
.c.o:
$(CC) $(CFLAGS) -o $# -c $<
(observe there's a -c option to the compiler indicating to compile only and don't link, we'll return here below) which means that once you detect the .o is outdated (as the dependencies on .c and .hs mark) it will be compiled with the above command, which result in:
gcc -Wall -o execFile.o -c execFile.c
making the appropiate compilation.
Other thing is the dependencies of the executable file. These have to be included, as make(1) doesn't know which object files form your final executable. In this case, assuming you have your program execFile depend on execFile.o and a.o, b.o and c.o, I normally use to write:
execFile_objs = execFile.o a.o b.o c.o
execFile: $(execFile_objs)
$(CC) $(LDFLAGS) -o $# $(execFile_objs)
so any of the .os is changed (because an indirect change in a source file) the whole program is linked again (but only the touched files are compiled)
NOTE
In the case (not normal) that you have a Makefile to create a program that has only one source file and several include files you can compile each time the whole thing each time you modify one source file, in this way:
execFile: execFile.c functions.h newDataTypes.h
$(CC) $(CFLAGS) $(LDFLAGS) -o $# execFile.c
This will execute
gcc -Wall -o execFile execFile.c
Observe that there is no -c (compile only, don't link) option in this command.
There's no mention of the include files (they are included because of the #include directives in the code... and you only state here that the executable depends also (and have to be built) in case any of the .h files are modified.
Automatic dependency rules are a little confusing at first, as they induce you to think there are such rules to make any kind of file from any other kind of file (well, there are for .c -> .o files, and .c -> <nothing> to compile directly to an executable) normally you have to include dependencies in such cases when your target depends on more files than the automatic rule states. In such cases, it is very important not to include any command, so the compiler selects the automatic rule (when you don't include a command to generate the target, the make(1) program tries to use a default rule for it, or nothing at all if you have not included commands, it only assumes your dependencies are indirect through this fake target --- and, as this fake target is not built in the process, it will fail always and be followed)

Makefile for C Program

I am trying to use this Makefile for a C Program. Could you please share with me a way how I can understand the Make utility better? I am trying the following:
# stack/Makefile
CC := gcc
CFLAGS += -std=c99
CFLAGS += -Wall
CFLAGS += -Wextra
CFLAGS += -g
VPATH = main src
all: bin/main.exe clean run
bin/main.exe: bin/main.o bin/stack.o
$(CC) -o $# $^ $(LDFLAGS) $(LDLIBS)
bin/main.o: main.c
bin/stack.o: stack.c stack.h
bin/%.o: %.c
$(CC) $(CFLAGS) -c -o $# $<
demo:
../bin/main.exe
clean:
rm -f bin/*.o
run:
bin/main.exe
.PHONY: all clean run
And I getting this message:
gcc -std=c99 -Wall -Wextra -g -c -o bin/main.o main.c
error: unable to open output file 'bin/main.o': 'No such file or directory'
1 error generated.
make: *** [bin/main.o] Error 1
The error stems from the fact that your Makefile wants to
generate the executable and object files in subdirectory bin but it
contains no rule to ensure that bin exists when it is
needed. As #JonathanLeffler comments, you can solve that
just by manually creating bin yourself.
But it is often desired that a Makefile itself will ensure
that a subdirectory, or some other resource, exists when it
is needed, and you probably assumed that the pattern-rule
bin/%.o: %.c
would create bin as needed. It won't.
Your Makefile can ensure the existence of bin if you
amend it like this:
Somewhere below the all rule, add a new target:
bin:
mkdir -p $#
This is to make the bin subdirectory if it doesn't exist.
Then change the rule:
bin/%.o: %.c
$(CC) $(CFLAGS) -c -o $# $<
to:
bin/%.o: %.c | bin
$(CC) $(CFLAGS) -c -o $# $<
The additional | bin is an example of an order-only prequisite
It means: If any of the targets (the bin/%.o things) needs to be remade from any of preceding prequisites (the ones before |, i.e. the %.c
things), then bin must be made first. So, as soon as anything needs to be made in bin, bin will be made first.
There is another more basic flaw in your Makefile. all is dependent on clean, so every time you successfully build
your program the object files are deleted. I understand that you intend this, but it entirely
defeats the purpose of make, which is to avoid the need to rebuild everything (object files, executables) every
time by instead just rebuilding those things that have become out-of-date with respect to their prerequisites.
So all should not depend on clean, and then an object file will be recompiled only if it needs to
be recompiled, i.e. is older than the corresponding source file. If and when you want to clean out the
object files, run make clean.
Finally, your demo rule:
demo:
../bin/main.exe
is inconsistent with the others. The others assume that the bin where the executable
is put is in the current directory. The demo rule assumes it is in the parent of
the current directory. If you correct the demo rule then it will be identical to
the run rule, so it is superfluous, but if it were not superfluous then it should
be added it to the .PHONY targets.
The best way to learn the proper way to use makefiles is to read the manual. Also, you can Google for some simple tutorials.

Creating a Makefile in Raspbian

I'm trying to create a Makefile for my C program in Raspbian (Raspberry Pi).
My program consists of a bunch of .c and .h Files. I've looked at countless Makefiles, but I just don't unterstand how it works with multiple files. There are always .o files in the Makefile but as I understand object files are the result of compiling, so I dont have any o. Files as I am trying to compile my .c Files.
Please explain to me how this works.
Edit:
Thank you. So I tried this and it starts compiling but there are errors 'multiple definition'. Example:
These are my Files:
main.c main.h
calibration.c calibration.h
file.c file.h
frame.c frame.h
gamepad.c gamepad.h
gpio.c gpio.h
uart.c uart.h
types.h
this is my makefile:
all: main
main: main.o calibration.o file.o frame.o gamepad.o gpio.o uart.o
%.o: %.c
gcc -c -std=c99 -Wall $< -o $# -lncurses
Where can i put 'types.h'?
With every file I get errors 'multiple definitions'
A very simple but typical makefile could look like this
SOURCES = source1.c source2.c source3.c
OBJECTS = $(SOURCES:%.c=%.o)
TARGET = myExecutable
$(TARGET): $(OBJECTS)
gcc $^ -o $#
%.o: %.c
gcc -c $< -o $#
The complicated parts:
SOURCES = source1.c source2.c source3.c This is a variable definition, it assigns the string "source1.c source2.c source3.c to the variable SOURCES.
$(SOURCES:%.c=%.o) This is a shorthand for the patsubst text function. It takes all text from the $(SOUCES) variable, and replaces the pattern %.c with %.o, i.e. it takes e.g. the string source1.c and replace it with source1.o.
$(TARGET): $(OBJECTS) This makes myExecutable depend on all object files, meaning if one object file is modified then the command in the rule will be executed.
gcc $^ -o $# This calls the gcc command, passing all dependencies ($^) as arguments (that is, all object files), and tells gcc to output a file with the name of the target ($#).
%.o: %.c This is the rule that makes object files depend in their source file. So if you have source1.c then source1.o will depend on that source file.
gcc -c $< -o $# This is the command that compiles the source file (the first dependency, $<) to an object file (with the -c option) and name it as the target of the rule ($#).
Also note that if you invoke make without a specific target, then the first rule will be selected. In the case of the above makefile, it will be the $(TARGET): $(OBJECTS) rule which will make sure that all object files are build from the source files, and then link the object files into the resulting executable.
The basic syntax of a make rule is:
target … : prerequisites …
recipe
…
…
On the left of the semicolon are the targets. The targets are your object files(.o). On the right of the semicolon are the files that you will need to create this file. Those files are the source files(.c).
Lets give a basic example of what such a rule could look like.
%.o: %.c
gcc -c $< -o $#
The % sign is a wildcard. %.o means everything that ends with .o. So, if you want to make an object file, you can say make file.o, and make will try to find a rule with which it can make this target. This happens to be the rule I just showed as an example, because file.o matches %.o.
Then the recipe. This is what will be executed. Usually it's about invoking the compiler(gcc), and feeding it the source file to generate the object file. That's what we do with gcc -c $< -o $#. The $< and $# mean target and prerequisites respectively.
So, what happens when you 'just' want to build your program? You usually will type make, and it will build. The default rule that's used when you type make, is all. So, if you make a rule about all, then you can specify what files you want to create to build your program. Example of such a rule:
all: main
Then, when make is invoked, it will find that rule and finds out it needs main. To create main you need another rule:
main: file.o
This rule says that to build main, you need file.o. So, when you put all of the example rules together you get this:
all: main
main: file.o
%.o: %.c
gcc -c $< -o $#
Note that you can specify more than one file, so instead of file.o, you can say file.o main.o other_file.o etc. Every prerequisite that you specify will be made, if they can find a rule to make it.

What is wrong with this Makefile? (header files not found)

I am modifying an old makefile in order to build a C extension for postgreSQL. The Makefile currently looks like this:
PGLIB = /usr/lib/postgresql/8.4/lib
PQINC = /usr/include/postgresql/8.4/server
CC=gcc
override CFLAGS+= $(CFLAGS_SL) -DPG_AGGREGATE
SHLIB = pg_myextlib
SRC = foo.c \
foobar.c
OBJS = foo.o \
foobar.o
all: $(OBJS)
$(CC) -shared -o $(SHLIB)$(DLSUFFIX) $(OBJS) -I$(PQINC)
cp *.so $(PGLIB)
clean:
rm -f $(SHLIB) $(OBJS)
The error I get when I run make is:
common.h:58:22: error: postgres.h: No such file or directory
Which suggests that the include path is not being added (the file exists in $PQINC).
Its a long time since I wrote the Makefile - and I haven't written many since. As an aside, I am pretty sure that 'shared' is not the gcc flag to build shared libs on Ubuntu (my current dev box) - I think the flag should be 'fPIC' - can someone confirm this?
I am runing gcc v4.4.3 on Ubuntu 10.0.4 and compiling for use with PG 8.4
Try moving the -I$(PQINC) from target all to the end of line that starts with override CFLAGS.
Placing -Isomething on the compiler line which turns object files, like those in $(OBJS), into executable will have no effect whatsoever.
You need to do it when you compile the source files.
Since your makefile doesn't explicitly show the rule for processing source files, it may well be using a default one, which is incredibly unlikely to know about PQINC.
You seem to be using the default rules to build foo.o from foo.c, which doesn't have your -I. Try adding the following rule to your Makefile:
.c.o:
$(CC) $(CFLAGS) -c $< -o $# -I$(PQINC)

Resources