John
John

Reputation: 788

Automatic actions by makefile

I have written simple code *make_test* to test the functionality of makefile. The folder structure is as follows:

  1. include folder contains maths.h

    float add(float a, float b) 
    {
        return a+b;
    }
    
  2. the main file contains the following code:

    # include <stdio.h>
    # include <include/maths.h> 
    
    int main(int argc, char** argv) 
    {
        float a=1; 
        float b=4; 
    
        printf("%f + %f = %f\n", a, b, add(a, b));
        return 0;
     }
    
  3. The makefile which contains the following:

    IDIR = -I.
    DEPS = ./include/maths.h
    CC= gcc -Wall -g $(IDIR)
    
    program: make_test.o
    
    %.o: test/%.c $(DEPS)
        @echo "Rule 1 was called"
        $(CC) -o $@ $<
    
    %.o: test/%.c $(DEPS)
        @echo "Rule 2 was called"
        $(CC) -o $@ $<
    
    %.o: test/%.c $(DEPS)
        @echo "Rule 3 was called"
        $(CC) -o $@ $<
    

Note that there are test/%.c statements that have been deliberately inserted for testing. There is no test folder. If I make a change in main file and I type make on the command line, I get

    gcc -Wall -g -I.    -c -o make_test.o make_test.c

My question is that I have not added -c flag anywhere then why does it appear at the output? Shouldn't there be a "Nothing to do" output because no dependency either exists (test/%.c) or is changed (include/maths.h)?

Thanks,

Upvotes: 1

Views: 86

Answers (1)

MadScientist
MadScientist

Reputation: 101061

Make contains a large number of built-in rules. You can see them by running something like this: make -p -f /dev/null. One of these rules is being used to compile your code, and it contains the -c flag.

Why is a built-in rule being used? Because your rules you defined do not match. They tell make how to build a .o files from a .c file in the test subdirectory. But the make_test.c file is not in the test subdirectory, so those rules can't be used by make. Thus make looks at its built-in rules to find a rule that can build a .o from a .c in this same directory, and finds one, and uses that.

If you move your make_test.c file into the test subdirectory, then your rules will be used.

Note, though, that make is correct here: you must add the -c flag to the compiler invocation if you want .o output. Your rules will not create an object file, they'll create an exectuable named xxx.o which is pretty confusing.

Upvotes: 5

Related Questions