Ich schreibe Makefile-Regeln wie diese:
out/%.x: ...
mkdir -p $(@D)/
...
Ich beabsichtige, dieses Makefile ( -j
) zu parallelisieren, wodurch viele mkdir -p
's gleichzeitig ausgelöst werden.
Ist das sicher? Oder muss ich mich vor Problemen schützen, indem ich sicherstelle, dass mkdir -p
es nur einmal passiert?
(Notizdas mkdir -p
ist nicht unbedingt eine einzelne Operation auf Dateisystemebene, im Gegensatz zu mkdir
.)
Antwort1
Die Begründung fürPOSIXmkdir
sagt
Da kein Fehler auftritt, wenn bereits eine Pfadkomponente vorhanden ist,-PDie Option ist auch nützlich, um sicherzustellen, dass ein bestimmtes Verzeichnis existiert.
Dies lässt darauf schließen, dass die parallele Nutzung sicher sein sollte. Ich kann Ihre Zweifel angesichts der Möglichkeit von Races verstehen, also schauen wir uns eine Implementierung an …
In GNU wird coreutils
diese -p
Option letztendlich vonmkancesdirs
, das eine hilfreiche Beschreibung enthält, die Ihre Ängste zerstreuen sollte:
Stellen Sie sicher, dass die übergeordneten Verzeichnisse von FILE vorhanden sind. Verwenden Sie dazu einen Algorithmus, der auch dann funktionieren sollte, wenn zwei Prozesse diese Funktion parallel ausführen.
(Anstatt sofort auf Fehler zu reagieren mkdir
, versucht es, chdir
in jedes Komponentenverzeichnis zu gelangen und schlägt nur fehl, wenn das fehlschlägt.)
Wenn Sie GNU Make verwenden, können Sie dessenSekundärerweiterungum Verzeichnisse auf die gleiche Weise wie andere Voraussetzungen zu behandeln:
.SECONDEXPANSION:
%/:
mkdir -p $@
out/%.x: $$(@D)/ ...
...