2014-07-16 7 views
6

Für ein Projekt von mir ich automatisch am Makefiles und einschließlich ihnen, wie diese zu erzeugen:erzeugt einschliessen Make-Datei ohne Warnmeldung

all: 
    @echo 'SUCCESS is $(SUCCESS)' 

clean: 
    rm depend.mk 

depend.mk: 
    @echo 'Creating [email protected]' 
    @echo 'SUCCESS := 1' > [email protected] 

.PHONY: all clean 

include depend.mk 

Dies funktioniert, aber die sind Linie eine Warnmeldung:

$ make 
Makefile:13: depend.mk: No such file or directory 
Creating depend.mk 
SUCCESS is 1 

Ich möchte die erste Warnzeile sagen, dass depend.mk nicht existiert. Ich weiß, dass es nicht existiert, da ich eine Regel geschrieben habe, um es zu generieren, also ist die Warnung unnötig (es sei denn natürlich, es gibt keine Regel dafür). Ich möchte NICHT machen, um den Fehler zu ignorieren, wo die enthaltene Datei nicht existiert und es keine Regel dafür gibt, so dass include mit einem - vorangestellt wird, um den Fehler zu ignorieren, funktioniert für mich nicht. Ich möchte etwas Ähnliches wie bash's Konvention von Piping stderr zu/dev/null wie some_cmd 2>/dev/null, aber für die Einbeziehung in make.

Das obige Beispiel ist ein sehr vereinfachtes Beispiel für diesen Fall. In meinem aktuellen Projekt werden viele automatisch generierte Makefiles (über die automatische Abhängigkeitsgenerierung von clang) eingebunden, was bedeutet, dass ein neuer Lauf von make meinen Bildschirm mit diesen Warnmeldungen überfluten wird.

Ist so etwas möglich, oder muss ich mich nur mit den lästigen Warnmeldungen herumschlagen?

+0

Die Clang automatische Abhängigkeitsdateien haben bestimmte Regeln für sie? Sie werden nicht als Nebeneffekte der Kompilierung generiert? –

+0

@EtanReisner Sie sind Musterregeln wie '$ (BUILDROOT) /% .d: $ (CURTOP) /% .c' wo das Rezept ist $ (CPP) $ (CPPFLAGS) -MM -MG -MT $ @ -MT $ (Basisname $ @). o -MF $ @ $ <', so dass sie generiert werden können, bevor etwas erstellt wird. – C0deH4cker

+1

Müssen Sie sie generieren, bevor etwas gebaut wird? Verliert das nicht nur Zeit? Wenn die c-Datei kompiliert werden muss und clang sowohl die Objektdatei als auch die '.d'-Datei zur gleichen Zeit ausspucken kann, warum sollte es dann in zwei Durchläufen erledigt werden? –

Antwort

1

Ich versuchte viele (viele!) Dinge zu sehen, ob ich die Fehlermeldung verhindern oder umleiten konnte. Kein Glück.

Aber als ich versuchte -include (einschließlich mit einem führenden Bindestrich), es hat keinen Fehler geben, und make mit clean, all, depend.mk und ‚default‘ gearbeitet alles richtig und wie erwartet.

Gibt es einen bestimmten Grund, warum Sie die -include Variante nicht verwenden wollten? Scheint, genau das zu tun, was Sie suchen, und ändert nicht, wie das Makefile in irgendeiner Weise funktioniert, zeigt nur nicht den Fehler während des ersten Durchlaufs durch das Makefile an.

+1

Das Problem bei der Verwendung von '-include' besteht darin, dass, wenn einige der Abhängigkeitsdateien aus irgendeinem Grund nicht generiert werden können, keine Fehlermeldung angezeigt wird. Dies führt zu Problemen auf der ganzen Linie, wie z. B. schwer zu defekten Builds zu diagnostizieren oder Build-Produkte nicht automatisch zu aktualisieren, ohne auf eine 'make clean' zurückzugreifen. Ich möchte 'make', um mich anzubrüllen, wenn es versucht, eine Datei einzuschließen, die keine Erstellungsregel hat. – C0deH4cker

+0

Aber unter Berücksichtigung Ihrer Makefile-Regeln wird depend.mk unbedingt gemacht, daher sollte es immer verfügbar sein. Das '-include' __ONLY__ unterdrückt einen Fehler in einer nicht vorhandenen Datei. Jeder Abfall in der Datei führt erwartungsgemäß zu Fehlern. Sie sollten Logik hinzufügen, um zu überprüfen, ob "depend.mk" korrekt am Ende der Befehle erstellt wurde, die "depend.mk" erzeugen. Es gibt keinen anderen Ort, an dem es logisch wäre, seine Existenz oder seinen Inhalt zu testen. Make führt die Befehle aus, wenn sie fehlschlagen (und Sie setzen cmds nicht mit '-'), dann schlägt der Make-Prozess fehl. – lornix

+0

Bitte haben Sie Verständnis dafür, dass das Beispiel-Makefile, das ich zur Verfügung gestellt habe, eine viel einfachere Version dessen ist, was ich tatsächlich benutze (fast 1000 Zeilen Makefile-Code insgesamt). Es gibt Tonnen von Abhängigkeitsdateien, die automatisch von verschiedenen Orten mit unterschiedlichen Flags, Pfaden und Mustern erzeugt werden. Einige werden von '$ (eval'ed Funktionsaufrufen generiert, die beim Einschließen der Makefiles von Unterverzeichnissen auftreten (da dies ein nicht-rekursives make-Build-System ist, wie in dem Papier" Recursive Make Considered Harmful "erwähnt) "-include" zuerst, aber ich hatte Probleme mit schwer zu diagnostizieren Fehler, also habe ich es geändert. – C0deH4cker

2

Ich habe dieses Problem einige Male selbst angetroffen und (re-re-re-re) gelöst. Wirklich, das Problem liegt in der Denkumgebung, wenn die Abhängigkeitsdateien erzeugt und verwendet werden.

Dieser Link hat die detaillierte Beschreibung der „Auflösung“: http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/

Grundsätzlich kommt es auf die Tatsache, dass Abhängigkeitsdateien sind wirklich nur notwendig für den Wiederaufbau, nicht die ursprünglichen Gebäude der Bibliothek/ausführbar. Daraus folgt, dass Sie keine Regel zum Generieren von Abhängigkeitsdateien im Vorfeld benötigen (was weniger effizient ist), sondern Sie sollten diese während des Schritts der Objektdatei als Zwischendateien erzeugen, die als wertvoll markiert sind (also als Seite erstellt und verfolgt werden) -Effektdateien, die niemals automatisch bereinigt werden sollen Nachfolgende Builds haben dann die Dateien verfügbar, was genau das ist, was Sie insgesamt erreichen wollten. Sie können dann ein "-include" für die Abhängigkeitsdateien erstellen, mit dem Wissen, dass der Schritt zum Erstellen der Objektdatei fehlschlägt, wenn die Generierung der Abhängigkeitsdatei fehlschlägt, was einen sofortigen Fehler, wie Sie es vorziehen, bevorzugt und indirekt viel später.

Ich habe tatsächlich ein paar ziemlich große Build-Systeme, die diese Methode implementieren, und es funktioniert ziemlich gut, einschließlich derjenigen, die nicht-GNU Toolchains verwendet. Für einen externen Benutzer erscheint es identisch, aber es führt intern effizienter aus und versteckt möglicherweise wichtige Fehler nicht.