Präprozessormakros und Umgebungsvariablen



  • Hallöchen allezusammen 🙂

    Meine Frage bezieht sich auf Präprozessormakros und wie ich mit Hilfe derer momentan gesetzte Umgebungsvariablen ermitteln kann.
    Ziel ist folgendes: Wir programmieren ein recht umfangreiches System auf dem sich das Debuggen mit normalen Mitteln nicht durchführen lässt. Daher bauen wir uns selbst Debug Informationen ein. Hierzu haben wir eine debug.h geschrieben, welche ein paar Makros definieren, die uns eine Debugausgabe ermöglichen sollen. Soweit so gut. Das funktioniert auch. Nur wenn wir nun unsere Debugausgaben nicht drin haben wollen, müssen wir die Makros am Ende der debug.h neu definieren (und quasi nichts machen lassen). Dies führt dazu, daß beim compilieren tonnenweise Warnungen kommen, daß diese Makros redefiniert wurden. Diese Warnungen wollten wir weg bekommen und dachten uns nun so eine Art Verzweigung. WEnn eine entsprechende Umgebungsvariable beim compilieren gesetzt ist, dann soll er eben diese Makros auf eine Weise definieren, ist diese Umgebungsvariable nicht bzw. anders gesetzt, dann soll er eben die Makros "leere" definieren, so daß eben keine Ausgaben erscheinen.

    Nun zur eigentlichen Frage: wie kann ich innerhalb von Präprozessor-Anweisungen auf diese Umgebungsvariablen zugreifen bzw. diese Auslesen?
    So in der Art:

    #ifdef $DEBUG
    ...
    #else
    ...
    #endif

    und des weiteren, wie kann ich eine Umgebungsvariable temporär definieren im gleichen Aufruf von make, also daß ich in einer Anweisung diese Variable definiere (ähnlich wie "export PATH"), dann gleich im Atemzug make ausführen kann und (sofern möglich) daß sie am Ende von Make wieder nicht gesetzt ist.

    Ansonsten fällt mir nur der Umweg über

    export DEBUG=1
    make ...
    export DEBUG=0
    

    und dann halt bei den Präprozessormakros nur den Wert der Umgebungsvariable DEBUG auslesen.

    Hat da jemand eine Idee?

    Gruß Maddin

    P.S.: Hoffe ich hab mich nicht zu kompliziert ausgedrückt. 🙂



  • kruemeltee schrieb:

    Nun zur eigentlichen Frage: wie kann ich innerhalb von Präprozessor-Anweisungen auf diese Umgebungsvariablen zugreifen bzw. diese Auslesen?

    Garnicht.
    Üblicherweise macht man sowas im Makefile etwa wie folgt:

    ifdef DEBUG
    CXXFLAGS += -DHAVE_DEBUG
    endif
    

    debug.h:

    #ifdef HAVE_DEBUG
    #  define LOGX(x) fprintf(stderr, x)
    #else
    #  define LOGX(x)
    #endif
    

    und des weiteren, wie kann ich eine Umgebungsvariable temporär definieren im gleichen Aufruf von make, also daß ich in einer Anweisung diese Variable definiere (ähnlich wie "export PATH"), dann gleich im Atemzug make ausführen kann und (sofern möglich) daß sie am Ende von Make wieder nicht gesetzt ist.

    make DEBUG=1 all
    

    Setzt das ifdef im Makefile in Kraft

    BTW:
    Mit den Remote-Fähiogkeiten des gdb etc. kann ich mir irgendwie kaum vorstellen dass ihr keine Möglichkeit zum Debuggen habt...



  • Danke für die Info ... 🙂

    LordJaxom schrieb:

    BTW:
    Mit den Remote-Fähiogkeiten des gdb etc. kann ich mir irgendwie kaum vorstellen dass ihr keine Möglichkeit zum Debuggen habt...

    Hier gibts leider doch riesen Probleme. Wir programmieren zu Studienzwecken ein kleines Betriebssystem (vergleichbar Minix, nur noch SEHR am Anfang) in C++. Das Ding simulieren wir in bochs. Der Interne Debugger kann leider nur in Assembler debuggen (zumindest haben wir diese Erfahrung gemacht). GDB versuchen wir schon seit geraumer Zeit an bochs anzuhängen, nur findet aus einem unerfindlichen Grund gdb (bzw. ddd) keine Debugging Symbole.
    Daher haben wir es mit qemu versucht, welcher sich Anfangs als debug-freundlicher heraus gestellt hat. Doch nun sind wir bei Präemptiven Coroutinen angelangt, welche durch einen Timer regelmäßig unterbrochen werden. Daher ist schon der normale Ablauf nicht mehr linear (jeder Durchlauf läuft anders als der vorhergehende). Daher sind auch Fehler nur noch schlecht reproduzierbar. 😕
    Wenn Du diesbezüglich jedoch noch andere Ideen hast, wie man ein solches System funktionabel debuggen kann (und zwar so, daß ich den C++ Code noch sehen kann), dann wären wir Dir natürlich über alle Maßen Dankbar 🙂

    Dennoch Danke für Deine Hilfe ...

    mfg Maddin



  • kruemeltee schrieb:

    Nur wenn wir nun unsere Debugausgaben nicht drin haben wollen, müssen wir die Makros am Ende der debug.h neu definieren (und quasi nichts machen lassen). Dies führt dazu, daß beim compilieren tonnenweise Warnungen kommen, daß diese Makros redefiniert wurden. Diese Warnungen wollten wir weg bekommen und dachten uns nun so eine Art Verzweigung.

    LordJaxom hat ja schon die Lösung gebracht, aber dennoch ein Hinweis:
    Diese Warnungen bekommt man auch weg, indem man die Makros zunächst mit #undef undefiniert und erst dann mit #define neu definiert:

    #define log_debug(x) do { std::cerr << x << std::endl; } while(0)
    #undef log_debug
    #define log_debug(x)
    

    ergibt keine Warnung.

    Übrigens bevorzuge ich diese Art der Debug-Makros mit eine std::ostream. Dann geht auch so etwas:

    log_debug("Das Ergebnis ist " << a);
    

    Und zwar unabhängig vom Typ der Variablen a. Alles was einen Ausgabeoperator hat, kann ich dann in mein Debug-log schreiben. Und auch mit den richtigen Platzhaltern wie bei printf muß ich mich nicht rum schlagen.



  • Danke für die Antwort ...

    Ich hab jetzt verschiedene Möglichkeiten eingebaut, so wie Ihr es jetzt beschrieben habt. Ich kann jetzt beim compilieren DEBUG=0 und DEBUG=1 (bis 5) eingeben und bekomme 5 verschiedene Stufen ... 🙂

    War echt Hilfreich ... danke

    mfg maddin


Anmelden zum Antworten