Order-only dependencies in Makefile

May 2012


I created a C++ type representing a configuration file, using a template with non-type const char * parameters. One of the ways to do that is by having a vector of strings that name the parameters, and an enumerated type that indexes the vector, like this: src/option/wroptnames.cc


#ifndef def_cc_wroptnames
#define def_cc_wroptnames

#include <string>
#include <vector>

/**
   WROptNames is a global constant, so that its address(es) can be used as
   template arguments
 */

std::vector <std::string> WROptNames =
  { 
    "configfile",
    "configdir",
    "varlibdir"
  };

#endif // def_cc_wroptnames

    

src/option/wroptint.cc

enum WROptInt { configfile = 0, configdir = 1, varlibdir = 2 };
    

However, in order to keep the correspondence of names between the enum and the vector correct, the programmer must be very careful. So it's safer to generate src/option/wroptint.cc using gen_wroptint, the source of which is trivial, and left as an exercise to the reader ;)

The interesting point here is that generating source with a program that first must be compiled involving same source easily creates circular dependencies in Makefiles: wroptint.cc is generated using gen_wroptint, but a new wroptint.cc would merit rebuilding gen_wroptint as well. The fact that gen_wroptint is merely required to build wroptint.cc, but a newly built gen_wroptint does not imply that wroptint.cc needs to be rebuilt, can be conveyed to Make thusly:

src/option/wroptint.cc: src/option/wroptnames.cc | gen_wroptint
        ./gen_wroptint src/option/wroptint.cc
    

See order-only prerequisites under types of prerequisites in the Make manual.