-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Description
Description
What does make clean all mean? How can one create a target and clean it at the same time? The answer is that it does not make sense. This ill-defined command is used extensively in RIOT.
It could seem (if one has only a superficial understanding of make) that make clean all means make clean followed by make all. Well, that is not how make works, and if it behaves like that in certain circumstances it is only accidental.
What make does is execute all recipes needed to make the required targets, in any order, as long as dependencies are satisfied. In the case of parallel make ("-j") recipe execution may be simultaneous.
The reason make clean all works at all is because of hacks that make all depend on clean. It is a hack because under normal circumstances all does not depend on clean.
Why is make clean all even used
See also: this comment
Normally, one would type make clean followed by make all. The problem is that in the current implementation, the overhead of starting make is too big. This is caused mainly by the extensive use of immediate assignments (:=) combined with $(shell ...) which means there are lots of commands run on each time make is invoked.
On a big CI build, this overhead adds up and cleaning ends up taking considerable time. For this reason a hack was devised to make it possible to run both targets in a single invocation.
Steps to reproduce the issue
This issue is hard to reproduce, as it involves parallelism (and non-deterministic behaviour). For some examples, see
- examples/{javascript/lua}: correctly declare rules to embed scripts. #10456 Removing a (seemingly) unrelated rule caused builds to start failing.
- Makefile.include: remove rule to remake PKGs' Makefile.include #10344 This is the rule that got removed.
- Makefile.include: building in docker should be done after clean #10461 It also complicates docker integration.
- mcuboot.mk: Add mcuboot targets to BUILDDEPS. #10492 I thought I fixed it, but it turns out it is necessary to add conditional dependencies on "clean" for some targets.
Steps to fix
Removing all the code needed for make clean all, and banning it's usage will make our build system simpler and saner.
For this we must attack the root cause: high overhead, caused by unnecessary evaluations of variables containing costly shell invocations. The good news is that that overhead can be fixed.
On the other hand, in the case where those variables are needed, they should be evaluated only once.
Another cause of unnecessary evaluations is the indiscriminate use of "export" statements (see #10440 for an example).