Search code examples
makefilegnu-make

Can not comprehend this circular dependency in Makefile


Here is a simple Makefile that generates a circular dependency: test.cr <- test.cr.c

test: test.cr.c
    cp test.cr.c test

test.cr.c: test.cr
    cp test.cr test.cr.c

Why does GNU make consider this a circular dependency? How can I avoid it?


Solution

  • You can use make -d to see make's thinking. In this rule:

    test.cr.c: test.cr
            cp test.cr test.cr.c
    

    You haven't provided make with any rule to build test.cr so make will go looking for one in its default rule set (run make -pf/dev/null to see the complete set of builtin rules). It has a rule that knows how to build an executable from a .c file:

     %: %.c
            $(LINK.c) $^ $(LOADLIBES) $(LDLIBS) -o $@
    

    So it tries to see if this rule can be used to build test.cr from test.cr.c. To do this it needs to see if it can update test.cr.c and it finds you provided a rule that builds test.cr.c from test.cr... now you have a circular dependency.

    There are all kinds of ways to avoid this. You can change your filename from test.cr to test.cr.in or something so it has a different relationship with test.cr.c.

    You can remove all the built-in rules by running make -r. Or, in new-enough versions of GNU make you can add MAKEFLAGS += -r to your makefile to turn off the built-in rules.

    You can delete that particular built-in rule using:

    %: %.c
    

    (with nothing else).

    You can declare a do-nothing explicit rule for test.cr so make doesn't search for one in its database, like this:

    test.cr: ;
    

    There are other ways, by adding .cr as a suffix.