How to detect Makefile re-evaluation due to include - makefile

I have a Makefile (GNU make) which will re-evaluate itself under certain circumstances due to an include. I would like to be able to determine, during evaluation and before rule execution, whether this is the first "pass" or the second "pass" (the re-evaluation). Is there a way to do this?
I have tried exporting a variable, but this does not seem to work (it seems the re-evaluation is not treated as a sub-make, which I guess makes sense).
I am working on reformulating the Makefile to remove the re-evaluation but it's not simple for my application and I was hoping for a short-term fix...

Are you talking about the fact that make restart itself if any included files (with include) has been remade during the first attempt ? If so, you're looking for the MAKE_RESTARTS special variable, which (quoting the manual) will contain the number of times this instance has restarted

Related

Makefile rule with no target

I'm debugging a makefile, and in a macro expansion it creates a rule with no target (as so:)
: | directoryA
#echo running $#
...
I've looked it up online, and the makefile documentation seems to hint (but not explicitly state) that there should be at least one target.
With my current version of make (gnu Make 4.2.1), it's not killing me, but I'm just wondering whether this is considered undefined behavior or whether this is supported, and if so, what it should do.
I've looked it up online, and the makefile documentation seems to hint (but not explicitly state) that there should be at least one target.
Different makes may behave differently. They may even exhibit variant handling of specific makefile syntax matters depending on the content of the makefile -- for example, a makefile may be interpreted differently if it starts with a rule for the .POSIX: special target than an otherwise identical makefile without that rule is interpreted.
Overall, however, if you want some sort of general idea of what should be considered correct then the POSIX standard's defintion of make is a reasonably good baseline. It says:
Target rules are formatted as follows:
target [target...]: [prerequisite...][;command]
[<tab>command<tab>command...]
line that does not begin with <tab>
Target entries are specified by a <blank>-separated, non-null list of
targets, then a <colon>, [...]
(emphasis added). It furthermore goes on to say that
Applications shall select target names from the set of characters
consisting solely of periods, underscores, digits, and alphabetics
from the portable character set
, from which we can infer that the syntax description is talking about the rule text after macro expansion, since macro references can appear in the target lists of rules (or literally anywhere in a makefile, per the spec), but the characters $, (, ), {, and } appearing in macro references are not among those that can appear in targets.
That specification of makefiles' expected contents does explicitly state that target lists are non-empty, and it is reasonable to treat it as authoritative where your specific make's documentation does not override it.
I'm just wondering whether [an empty target list] is considered undefined behavior or
whether this is supported
Your combination of makefile and runtime macro values does not conform to the requirements of POSIX make. The spec does not define what should happen in this case, so in that sense the behavior is undefined, but "undefined behavior" isn't as strong a concept in this area as it is in, say, the C and C++ language specifications.
In view of that, I would account it a makefile flaw for any rule's target list to be empty (after macro expansion). Although the make you are presently using may accept it without complaint, other makes, including future versions of your present make, may reject it or worse.
Rule does expect one or more targets, there really are no two ways about it in the docs. For instance GNU make docs notation:
targets : prerequisites
recipe
Or 1p section manpage:
target [target...]: [prerequisite...][;command]
Illumos:
target [:|::] [dependency] ... [; command] ...
[command]
...
After all how would you refer to a target that had no name? I would assume no target rule should be an error...
However, I've tried different flavors of make (BSD, Illumos, GNU) and with varying degree of leniency (GNU make for instance seemed to also not care about syntax of prerequisites any more) or lack thereof they all seemed to have processed the line and possibly following tab indented block as a rule (with a recipe)... which then was ignored (also for the purpose of determining the default target).
I guess a rationale for this actually being consider valid Makefile... you could end up in this situation also with:
$(VAR):
#echo foobar
other:
#echo barbaz
In case VAR is undefined or empty, you'd end up with a such empty target as well.

Are there any practical reasons to use `-include` in a Makefile?

I was recently debugging a vague problem which turned out to be caused by a misplaced sub-Makefile which was conditionally included into a main Makefile by the -include directive. Mind the starting minus sign. According to GNU Make manual:
If you want make to simply ignore a makefile which does not exist or
cannot be remade, with no error message, use the -include directive
instead of include, like this:
-include filenames…
This acts like include in every way except that there is no error (not
even a warning) if any of the filenames (or any prerequisites of any
of the filenames) do not exist or cannot be remade.
For compatibility with some other make implementations, sinclude is
another name for -include.
The nastiest problem with this directive is that no diagnostics whatsoever are given when the sub-Makefile cannot be found. Needless to say, this complicates debugging a lot.
In fact, there was no real need to use it there, a regular include worked just fine and is much more robust. I understand the original author's intention for using -include. That sub-Makefile contained some "secret" stuff that was not meant to be shared with 3rd party engineers. But this functionality was never used in the end, and it could have been implemented in a more transparent way.
I wonder if there are other practical cases when -include is useful. Maybe some cases when one or several makefiles are dynamically generated during the build process?
Surely, the most useful application of -include is when the include file is auto-generated by make itself.
Remember that all include files also become make's targets automatically. So -include generated_file does not make make to fail prematurely, but implies that generated_file will be (re-)built using other rules in the current Makefile. This can be exploited in auto-dependencies generation, for example.
BTW. Another trick with 'include' is that include $(empty_var) also works without errors (i.e. is no-op).

Using Makefile variable before definition in included file

I've encountered a little problem during my Makefile learning adventure.
I have prepared two scripts. The first one is the main Makefile:
all:
#echo $(COMPONENTNAME)
include ~/Projects/tests/mk
And here's the mk file
COMPONENTNAME:=ISeeYou
Now, when I run
make all
I get
ISeeYou
I am not sure why... I was convinced that a variable must be defined before it is used. And the include is after COMPONENTNAME is being used. My suspicion is that all of the includes are done first, and then the target creation is started. Is that the case?
My suspicion is that all of the includes are done first, and then the target creation is started.
Yes, you are right.
All global sections in Makefile should be completely parsed before make is able to decide, which targets(and in which order) should be built. Target's recipes are evaluated only when it is needed to build target. This is explicitely stated in make manual:
The other way in which make processes recipes is by expanding any variable references in them. This occurs after make has finished reading all the makefiles and the target is determined to be out of date; so, the recipes for targets which are not rebuilt are never expanded.

Can MinGW Make be sped up without disabling implicit rules?

GNU Make under MinGW is known to be very slow under certain conditions due to how it executes implicit rules and how Windows exposes file information (per "MinGW “make” starts very slowly").
That previous question and all other resources on the issue that I've found on the internet suggest working around the problem by disabling implicit rules entirely with the -r flag. But is there another way?
I have a "portable" Makefile that relies on them, and I'd like to make it so that it does not take around a minute to start it up each time, rather than having to get the Makefile owner to alter it just for me.
You should use make -d to see all the things make is doing and try to see where the time is going. One common reason for lengthy make times are match-anything rules which are used to determine whether or not a makefile needs to be rebuilt. Most of the match-anything rules CAN be removed; they're rarely needed anymore.
You can add this to your makefile and see if it helps:
%:: %,v
%:: RCS/%,v
%:: RCS/%
%:: s.%
%:: SCCS/s.%
And, if you don't need to auto-create your makefile you can add:
Makefile: ;
(also put any included makefiles there that you don't need to auto-create).
ETA
It seems your real question can be summed up as, "why does make take so much longer to start on Windows than on Linux, and what can I do to fix that without changing makefiles?"
The answer is, nothing. Make does exactly the same amount of work on both Windows and Linux: there are no extra rules or procedures happening on Windows that could be removed. The problem is that Windows NTFS is slower than typical Linux filesystems for these lookups. I know of no system setting, etc. that will fix this problem. Your only choice is to get make to do less work so that it's faster, and the only way to do that is by removing built-in rules you don't need.
If the problem is you really don't want to edit the actual makefiles, that's simple enough to solve: just write the rules above into a small separate makefile, maybe something like speedup.mk, then set the environment variable MAKEFILES=speedup.mk before invoking make. Make will parse that makefile as well without you having to change any makefiles.

Multiple instances of the same target for make

I am working on a Makefile written by someone else in my lab and I see the following:
include /path/to/Makefile.inc
TARGET_A: pre_req_1 pre_req_2
cmd_1;
cmd_2;
...
When I look at /path/to/Makefile.inc I see that it also includes a target TARGET_A
with other pre-requisites and recipes.
Is this a normal practice? (and would it work?) Would make treat the two rules separately? Can we safely make any assumptions about which one is considered first?
It is a dangerous practice since it is confusing to know which one is applied.
The "include" will act has if the included file content was in the Makefile, and the targets will be overrided while reading the Makefile. So, the last target will be honored, and the first one (in the included file) will be ignored.

Resources