Makefile generator creates two files

前端 未结 2 1725
一整个雨季
一整个雨季 2021-01-23 04:53

I have a generator program that creates two version files, say ver.h and ver.cpp. My ultimate build target depends on both of these files, and the rule

相关标签:
2条回答
  • 2021-01-23 05:31

    See 10.5.1 Introduction to Pattern Rules specifically the last paragraph:

    10.5.1 Introduction to Pattern Rules

    ...

    A pattern rule need not have any prerequisites that contain ‘%’, or in fact any prerequisites at all. Such a rule is effectively a general wildcard. It provides a way to make any file that matches the target pattern. See Last Resort.

    ...

    Pattern rules may have more than one target. Unlike normal rules, this does not act as many different rules with the same prerequisites and recipe. If a pattern rule has multiple targets, make knows that the rule’s recipe is responsible for making all of the targets. The recipe is executed only once to make all the targets. When searching for a pattern rule to match a target, the target patterns of a rule other than the one that matches the target in need of a rule are incidental: make worries only about giving a recipe and prerequisites to the file presently in question. However, when this file’s recipe is run, the other targets are marked as having been updated themselves.

    So you could use something like this:

    v%r.h v%r.cpp:
            ./gen/version/program
    

    I believe you need that odd patterning to have make consider the pattern to match (I don't believe it will match % against an empty string as ver%.h ver%.cpp would need). (I can't find reference to this in the manual at the moment though.)

    0 讨论(0)
  • 2021-01-23 05:39

    Using the phony target as the prerequisite is a bad idea. program will be run even if ver.* files exist, which is a false positive error.

    More subtly, GNU Make is only guaranteed to update its file timestamp, if that file is a target of a rule with a recipe. So here, even though program is always run, anything that in turn depends on ver.* files might not get updated at all!

    In my opinion it is best to not make up unnatural patterns for each target, but instead, go explicit:

    There is a "main" file that you are generating, that is ver.cpp. Use the "no-op" recipe ; for the other one, which can be put on the same line like this:

    ver.h: ver.cpp ;
    ver.cpp: Makefile
        ./gen/version/program
    

    This method starts with what you wrote, but adds the very important ;.

    If you did not have a natural candidate for the "main" file, then in my opinion it is best to use a "sentinel":

    ver.h ver.cpp: sentinel ;
    
    sentinel: Makefile
        ./gen/version/program
        touch $@
    

    Again, this method is similar to one of your methods, but very importantly, does not use a phony, but a real file.

    0 讨论(0)
提交回复
热议问题