0
votes

In my project, I have an action that produces several output files simultaneously. One of them contains rules like the compile target.

Here is a small example makefile of what I would like to run.

SHELL = cmd.exe
rules_InputFiles = makefile
rules_OutputFiles = exec\rules.mk exec\other.mk

$(rules_OutputFiles): exec\rules.temp

.INTERMEDIATE: exec\rules.temp
exec\rules.temp: $(rules_InputFiles)
    $(info == generating rules.mk and rules2.mk (due to $?)  ==)
    if not exist exec mkdir exec
    @echo compile: >exec\rules.mk
    # precede the second @echo with a tab character
    @echo <tab>@echo !!!! compiling !!! >>exec\rules.mk
    @echo compile2: >exec\other.mk
    # precede the second @echo with a tab character
    @echo <tab>@echo !!!! compiling2 !!! >>exec\other.mk    

-include exec\rules.mk

Invoking make compile for this makefile results in the make error message:

*** No rule to make target 'compile'.  Stop.

The second invocation runs normal with the output !!!! compiling !!! I would like run make only once, since this should run on a build server without interaction.

This makefile is a combination of the rules in constructed included makefiles and the generation of multiple targets with an intermediate target.

My question is: can this makefile be modified to achieve my goals?

I tried several workarounds. One of them is to omit the intermediate target and use rules.mk as a marker file. This corresponds to the article of mad-scientists, but doesn't include the necessary dependencies.

Restating the rule as $(rules_OutputFiles): $(rules_InputFiles), leads to the recipe executing twice, which is not desired.

1

1 Answers

0
votes

This isn't to do with INTERMEDIATE, it's because you are lying to make.

In its initial are-the-makefiles-up-to-date stage, make sees that it has to update exec/rules.mk. Before doing that, it has to update exec/rules.temp.

  • exec/rules.temp does not exist
    • Runs the recipe for exec/rules.temp
  • Recipe for exec/rules.mk does not exist
    • make does nothing, and sadly does not notice that this file was created magically as a side effect of the recipe for exec/rules.temp

To prove this is a case, just add a recipe for exec/rules.mk. Anything will do. The simplest possible thing is:

exec/rules.mk: ;

With this simple addition, make will now check to see if exec/rules.mk has actually been updated since it last read (or failed to read) it. Job done. (Apart from leaving your makefile with a dodgy style that is. Moral: Your life will be much much happier if you do not lie to make.)