2016-09-14 2 views
1

Lassen Sie mich meine Situation erklären: Ich habe ein Programm, das verschiedene Arten von Modellen enthält (sagen wir 10, aber die tatsächliche Anzahl ist ziemlich hoch). Alle diese Modelle haben einen Namen und die entsprechende Datei "model1.cu" und "model1.h". Alle diese Dateien haben eine Funktion, die eine Gleitkommazahl erzeugt und sie in allen Dateien mit den gleichen Argumenten zurückgibt (sagen wir float returnfunction(float voltage)). Diese spezielle Funktion wird in der Hauptdatei benötigt. In der Make-Datei ich eine Option gesetzt haben, so dass Sie nur den Code für das Modell kompilieren Sie werden die Berechnung wie folgt:Makro in Makefile? Bedingte h-Datei-Aufnahme?

ifdef MODEL1 
SRCS := model1.cu 
OBJS := model1.o 
endif 

ifdef MODEL2 
SRCS := model2.cu 
OBJS := model2.o 
endif 

SRCS += main.c 

Jetzt kann ich das richtige Modell auswählen, indem Sie „MODEL1 = 1 machen“. Das Problem tritt in der Hauptdatei auf. Die Funktion returnfunction(float voltage) ist in model1.h definiert, also sollte ich sie einschließen. Aber wenn ich schließe

#ifdef MODEL1 
#include "model1.h" 
#endif 

#ifdef MODEL2 
#include "model2.h" 
#endif 

in meiner main.c Datei, erhalte ich die Fehlermeldung, dass die Funktion returnfunction ist nicht überall definiert. Gibt es eine Möglichkeit, die richtige h-Datei in meine Hauptdatei aufzunehmen? Vorzugsweise mit dem, dass ich bereits kompilieren mit MODEL1 = 1.

Jede Hilfe wird sehr geschätzt!

+2

Übrigens ist ein sauberer Weg dies zu tun, jedes Modell in ein separates Unterverzeichnis zu legen, mit Dateien, die z. 'model.cu' und' model.h'. Setzen Sie 'VPATH' und fügen Sie ein' -I' Flag aus Ihrem Makefile, dann können Sie 'SRCS: = model.cu',' OBJS: = model.o' und generisch '#include ' in Ihrem 'main.c '. –

+0

Ich mag Ihre Idee, aber könnten Sie auf die Verwendung von VPATH und -I angeben? Ich bin nicht mit allen möglichen Optionen in einem Makefile vertraut und die Dokumentation ist oft sehr schwer für mich zu verstehen. Was ich gerne wissen würde, sind die Zeilen, die Sie in das Makefile schreiben würden (angenommen, die Map heißt: NewModel und enthält model.cu und model.h) (der Rest des Konzepts, das ich bekomme). Ist es etwas wie: #ifdef MODEL1 VPATH = -I./NewModel #endif? – Tim

+1

Zu lang für einen Kommentar, also habe ich eine Antwort dafür geschrieben, es fallen im Grunde alle 'ifdef', die Sie dort haben. Es ist nur ein Vorschlag, die angenommene Antwort wird Ihren geposteten Code reparieren. –

Antwort

2

Sie können Ihrem Makefile für jedes Modell, das Sie haben, einfach eine Präprozessordefinition hinzufügen. Zum Beispiel im Fall von MODEL1 = 1:

ifdef MODEL1 
SRCS := model1.cu 
OBJS := model1.o 
CFLAGS += -DMODEL1 
endif 

Angenommen Sie haben die implicit rules verwenden, wird die modifizierte CFLAGS auf jede Datei übergeben werden, die kompiliert wird. Wenn Sie Ihre eigene Regel verwendet haben, um main.c zu kompilieren (und nicht CFLAGS verwenden), könnten Sie eine Variable erstellen und sie explizit übergeben.

1

Die andere Antwort ist auf den Punkt und behebt Ihre fehlenden #define. Ich werde den Kommentar, den ich hinterlassen habe, auf eine sauberere/trockenere Weise erweitern, um dies zu tun.

Das erste Stück ist jedes Modell in einem eigenen Verzeichnis mit gemeinsamen Source/Header-Namen. Zum Beispiel:

├── models 
    ├── model1 
    │ ├── model.cu 
    │ └── model.h 
    ├── model2 
    │ ├── model.cu 
    │ └── model.h 
    └── ... 

(Sie können das Top-Level models Verzeichnis ablegen, spielt keine Rolle)

Wir gehen mit enthalten Pfade spielen, so können Sie die ganzen #ifdef Sachen fallen aus Ihrem main.c und ersetzen Sie es durch eine einzige #include <model.h>.

Als nächstes, lassen Sie uns ein bisschen schlauer sein, wie wir das Modell spezifizieren. Anstatt MODEL1, MODEL2 usw. verwenden zu müssen, verwenden wir eine generische MODEL Variable, die den Modellnamen annimmt, so dass der make-Befehl wie MODEL=model1 make aussieht (wenn getrennte Vars eine harte Anforderung sind, gibt es Möglichkeiten, es ohne Tonnen ifdef s zu machen.) aber es ist immer noch hässlicher).

An diesem Punkt das Makefile zu schreiben wird trivial:

SRCS := models/$(MODEL)/model.cu main.c 
OBJS := $(addsuffix .o,$(basename $(SRCS))) 
CFLAGS += -Imodels/$(MODEL) 

Ich weiß nicht, wie Sie SRCS und OBJS später im Makefile sind Handhabung, damit ich addsuffix und basename nur verwendet, um ein .o zu schlagen in dort, aber Sie können es nach Ihren Bedürfnissen ändern.Ich füge das Modellverzeichnis den Include-Pfaden über CFLAGS hinzu, so dass es das richtige aufnimmt.

Sie könnten auch Quellen wie folgt angeben:

VPATH := models/$(MODEL) 
SRCS := model.cu main.c 

Da make in VPATH für Quellen suchen.

Etwas anderes Material: Wenn Sie noch ein C #define benötigen, können Sie es über CFLAGS hinzufügen. Wenn Sie einige gemeinsame Sachen in Ihren .h Dateien haben, denken Sie darüber nach, es in ein Top-Level .h umzuwandeln, welches dann #include <model.h>. Wenn Ihr Compiler es unterstützt, könnte #include_next auch praktisch sein.