Make file Doesn't detect changes in source files

Viewed 1693

I am very much new to make files , I am facing very basic problem , My Makefile doesn't detect changes I made to source files . The problem is , when I first time generate consoleapp binary from my source file i get expected output . But When I change source file again and when I run make again it says

make: 'consoleapp' is up to date , So what changes I have to give to make file so that it detects my changes

Below is my Makefile :

consoleapp: 
    g++  consoleapp.cpp  -o consoleapp

clean:
    rm -rf *.o  consoleapp

This is my Source File :

#include <iostream>
using namespace std;

int main()
{
    cout<<"I am ok  \n";  // I am changing this line again after giving make
    
    return 0;
}
2 Answers

make relies on the makefile author to tell it what each target's prerequisites are -- that is, which other targets or files affect the construction of the target in question, so that if they are newer or themselves out of date then the target is out of date and should be rebuilt. As your other answer already indicates, you do not designate any prerequisites for your targets, so make considers them out of date if and only if they don't exist at all.

That's actually problematic for both targets, albeit in different ways. For target consoleapp, which represents an actual file that you want to build, the failure to specify any prerequisites yields the problem you ask about: make does not recognize that changes to the source file necessitate a rebuild. The easiest way to fix that would be to just add the source file name to the recipe's header line, after the colon:

consoleapp: consoleapp.cpp
        g++ consoleapp.cpp -o consoleapp

Generally speaking, however, it is wise to minimize duplication in your makefile code, and to that end you can use some of make's automatic variables to avoid repeating target and prerequisite names in your rule's recipe. In particular, I recommend always using $@ to designate the rule's target inside its recipe:

consoleapp: consoleapp.cpp
        g++ consoleapp.cpp -o $@

It's a bit more situational for prerequisites. In this case, all the prerequisites are source files to be compiled, and furthermore there is only one. If you are willing to rely on GNU extensions then in the recipe you might represent the sources via either $< (which represents the first prerequisite), or as $^ (which represents the whole prerequisite list, with any duplicates removed). For example,

consoleapp: consoleapp.cpp
        g++ $^ -o $@

If you are not using GNU make, however, or if you want to support other people who don't, then you are stuck with some repetition here. You can still save yourself some effort, especially in the event of a change to the source list, by creating a make variable for the sources and duplicating that instead of duplicating the source list itself:

consoleapp_SRCS = consoleapp.cpp

consoleapp: $(consoleapp_SRCS)
        g++ $(consoleapp_SRCS) -o $@

I mentioned earlier that there are problems with both of your rules. But what could be wrong with the clean rule, you may ask? It does not create a file named "clean", so its recipe will be run every time you execute make clean, just as you want, right? Not necessarily. Although that rule does not create a file named "clean", if such a file is created by some other means then suddenly your clean rule will stop working, as that file will be found already up to date with respect to its (empty) list of prerequisites.

POSIX standard make has no solution for that, but GNU make provides for it with the special target .PHONY. With GNU make, any targets designated as prerequisites of .PHONY are always considered out of date, and the filesystem is not even checked for them. This is exactly to support targets such as clean, which are used to designate actions to perform that do not produce persistent artifacts on the file system. Although that's a GNU extension, it is portable in the sense that it uses standard make syntax and the target's form is reserved for extensions, so a make that does not support .PHONY in the GNU sense is likely either to just ignore it or to treat it as an ordinary rule:

.PHONY: clean

clean:
    rm -rf *.o  consoleapp

because your target has no dependence. Please use this codes that rely to all cpp file in current dir to update binary.

SRCS=consoleapp.cpp

consoleapp: $(SRCS)
        g++ $< -o   $@
Related