Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I make Makefile to recompile only changed files?

I have been struggling a bit to get make to compile only the files that have been edited. However I didn't have much success and all the files get recompiled. Can someone explain me why?

My files are:

main.c a_functions.c 

where main.c includes main.h and a_functions.c includes a.h

Here is my makefile:

CC=gcc CFLAGS=-Wall -I. -c EXEC_FILE=program1   all: program  a_functions.o: a_functions.c a_functions.c: a.h main.o: main.c main.c: main.h  objects: a_functions.c main.c     $(CC) a_functions.c main.c $(CFLAGS)  program: a_functions.o main.o     $(CC) a_functions.o main.o -o $(EXEC_FILE) 

Changing the makefile as per suggestions seems to have the same problem::

all: program  a_functions.o: a_functions.c a.h     gcc a_functions.c -c  main.o: main.c main.h     gcc main.c -c  program: a_functions.o main.o     gcc a_functions.o main.o -o program1 
like image 800
Pithikos Avatar asked Oct 19 '11 00:10

Pithikos


People also ask

How do I recompile with makefile?

Use the command `make' to recompile the source files that really need recompilation. Make the changes in the header files. Use the command `make -t' to mark all the object files as up to date. The next time you run make, the changes in the header files do not cause any recompilation.

How does makefile know a file changed?

Make works by inspecting information about files, not their contents. Make works out dependencies between targets and their dependencies, and then looks to see whether the files exist. If they do, it asks the operating system for the time and date the file was last modified.

What does clean do in makefile?

It allows you to type 'make clean' at the command line to get rid of your object and executable files. Sometimes the compiler will link or compile files incorrectly and the only way to get a fresh start is to remove all the object and executable files.

Can you compile a makefile?

The make utility requires a file, Makefile (or makefile ), which defines set of tasks to be executed. You may have used make to compile a program from source code. Most open source projects use make to compile a final executable binary, which can then be installed using make install .


2 Answers

The specific problem you're talking about -- Make rebuilds program1 (by relinking the objects) even when nothing has changed -- is in this rule:

program: a_functions.o main.o     gcc a_functions.o main.o -o program1 

The target of this rule is program, and Make assumes that it is a file. But since there is no such file, every time you run Make, Make thinks that this file needs to be rebuilt, and executes the rule. I suggest this:

program1: a_functions.o main.o     gcc a_functions.o main.o -o program1 

Or better, this:

program1: a_functions.o main.o     gcc $^ -o $@ 

Or better still this:

$(EXEC_FILE): a_functions.o main.o     $(CC) $^ -o $@ 

(And don't forget to change the all rule to match.)

A few other points:

  1. As @paxdiablo pointed out,

    a_functions.o: a_functions.c a.h main.o: main.c main.h 
  2. It doesn't make sense to link these objects together unless something in one (probably main.o) calls something in the other (probably a_functions.o), so I would expect to see a dependency like this:

    main.o: a.h 

    So I suspect that you have some misplaced declarations.

  3. You declare an objects rule, but never refer to it. So you never actually use it; Make uses the default rule for %.o: %.c. I suggest this:

    OBJECTS = a_functions.o main.o $(OBJECTS): %.o: %.c     $(CC) $< $(CFLAGS) -o $@ 

    (In which case you can change $(EXEC_FILE): a_functions.o main.o to $(EXEC_FILE): $(OBJECTS).) Or just this:

    %.o: %.c     $(CC) $< $(CFLAGS) -o $@ 
like image 177
Beta Avatar answered Sep 25 '22 20:09

Beta


Not sure if this is causing your specific problem but the two lines:

a_functions.c: a.h main.c: main.h 

are definitely wrong, because there's generally no command to re-create a C file based on a header it includes.

C files don't depend on their header files, the objects created by those C files do.

For example, a main.c of:

#include <hdr1.h> #include <hdr2.h> int main (void) { return 0; } 

would be in the makefile as something like:

main.o: main.c hdr1.h hdr2.h     gcc -c -o main.o main.c 

Change:

a_functions.o: a_functions.c a_functions.c: a.h main.o: main.c main.c: main.h 

to:

a_functions.o: a_functions.c a.h main.o: main.c main.h 

(assuming that a_functions.c includes a.h and main.c includes main.h) and try again.

If that assumption above is wrong, you'll have to tell us what C files include what headers so we can tell you the correct rules.


If your contention is that the makefile is still building everything even after those changes, you need look at two things.

The first is the output from ls -l on all relevant files so that you can see what dates and times they have.

The second is the actual output from make. The output of make -d will be especially helpful since it shows what files and dates make is using to figure out what to do.


In terms of investigation, make seems to work fine as per the following transcript:

===== pax$ cat qq.h #define QQ 1 ===== pax$ cat qq.c #include "qq.h" int main(void) { return 0; } ===== pax$ cat qq.mk qq: qq.o         gcc -o qq qq.o  qq.o: qq.c qq.h         gcc -c -o qq.o qq.c ===== pax$ touch qq.c qq.h ===== pax$ make -f qq.mk gcc -c -o qq.o qq.c gcc -o qq qq.o ===== pax$ make -f qq.mk make: `qq' is up to date. 
like image 33
paxdiablo Avatar answered Sep 22 '22 20:09

paxdiablo