Frage

Ich habe eine sehr große Code-Basis (sprich: Tausende von Modulen), die Code in zahlreichen Projekten geteilt hat, dass alle laufen auf verschiedenen Betriebssystemen mit unterschiedlichen C ++ Compiler. Unnötig zu sagen, kann den Erstellungsprozess aufrechterhalten werden, um eine ziemlich lästige Pflicht.

Es gibt mehrere Orte in der Code-Basis, wo sie den Code im wesentlichen nur aufzuräumen würden, wenn es eine Möglichkeit, den Pre-Prozessor ignoriert bestimmen #includes machen würde, wenn die Datei nicht im aktuellen Ordner vorhanden ist. Kennt jemand eine Möglichkeit, das zu erreichen?

Zur Zeit verwenden wir eine #ifdef um die #include in der Datei geteilt wird, mit einer zweiten projektspezifische Datei, die #defines, ob die #include im Projekt vorhanden ist. Dies funktioniert, aber es ist hässlich. Die Leute vergessen oft richtig die Definitionen zu aktualisieren, wenn sie Dateien aus dem Projekt hinzufügen oder entfernen. Ich habe in Betracht gezogen, eine Pre-Build-Tool Schreiben Sie diese Datei auf dem Laufenden zu halten, aber wenn es eine plattformunabhängige Art und Weise ist das ich würde es mit dem Prä-Prozessor zu tun, anstatt so viel lieber tun. Irgendwelche Ideen?

War es hilfreich?

Lösung

Im Allgemeinen wird dies durch die Verwendung eines Skripts durchgeführt, die auf einem Versuch, den Prä-Prozessor versucht, laufen die Datei an, einschließlich. Je nachdem, ob der Vorprozessor einen Fehler zurückgibt, aktualisiert das Skript eine generierte .h-Datei mit einem geeigneten #define (oder #undef). In der bash kann das Skript wie folgt aussehen vage:

cat > .test.h <<'EOM'
#include <asdf.h>
EOM
if gcc -E .test.h
 then
  echo '#define HAVE_ASDF_H 1' >> config.h
 else 
  echo '#ifdef HAVE_ASDF_H' >> config.h
  echo '# undef HAVE_ASDF_H' >> config.h
  echo '#endif' >> config.h
 fi

Ein ziemlich gründlich Rahmen für portably mit Portabilität Kontrollen wie diese arbeiten (wie auch Tausende andere) ist autoconf .

Andere Tipps

Little-Update

Einige Compiler könnte __has_include ( header-name ) unterstützen.

Die Verlängerung wurde hinzugefügt, um den C ++ 17-Standard ( P0061R1 ).

Compiler Unterstützung

  • Clang
  • GCC von 5.x
  • Visual Studio von VS2015 Update 2 (?)

Beispiel (von Klirren Website):

// Note the two possible file name string formats.
#if __has_include("myinclude.h") && __has_include(<stdint.h>)
# include "myinclude.h"
#endif

Quellen

Erstellen Sie einen speziellen Ordner für Header fehlen, und diese Ordner machen zum letzten
gesucht (dh Compilers spezifisch - letztes Element in "includes" Umgebungsvariable, so ähnlich)

Dann, wenn einige header1.h fehlen werden kann, dass Ordner erstellen einen Stub

header1.h:

#define header1_is_missing

Jetzt können Sie immer schreiben

#include <header1.h>
#ifdef header1_is_missing

   // there is no header1.h 

#endif

Der Präprozessor selbst kann nicht die Existenz von Dateien identifizieren, aber man kann sicherlich die Build-Umgebung so zu tun, verwenden. Ich bin meistens vertraut machen, die Sie so etwas wie dies in Ihrer Make-Datei zu tun erlauben würde:

ifdef $(test -f filename && echo "present")
  DEFINE=-DFILENAME_PRESENT
endif

Natürlich würden Sie eine Analog dies in anderen Build-Umgebungen wie Visual Studio finden müssen, aber ich bin sicher, dass sie existieren.

könnten Sie haben einen Pre-Build-Schritt ausführen, die eine Include-Datei erzeugt, die eine Liste von #defines enthält, die die Namen der Dateien bestehenden im aktuellen Verzeichnis darstellen:

#define EXISTS_FILE1_C
#define EXISTS_FILE1_H
#define EXISTS_FILE2_C

Dann schließen Sie die Datei aus Ihrem Quellcode, und dann können Sie Ihre Quelle der EXISTS_* testen definiert, um zu sehen, ob eine Datei existiert oder nicht.

So weit ich weiß, cav keine Richtlinie hat in Bezug auf die Existenz einer Datei.

Möglicherweise können Sie diese aus dem Makefile, mit ein wenig Hilfe erreichen, wenn Sie die gleiche verwenden auf allen Plattformen machen. Sie können das Vorhandensein einer Datei im Makefile erkennen:

foo.o: foo.c
    if [ -f header1.h ]; then CFLAGS+=-DHEADER1_INC

Wie @ Greg Hewgill erwähnt, können Sie dann Ihre #includes sein abhängig machen:

#ifdef HEADER1_INC
#include <header1.h>
#endif

Eine andere Möglichkeit: bevölkern ein Verzeichnis irgendwo mit der Länge Null Versionen von all den Header, die Sie wünschen sind optional. Übergeben Sie einen -I Argument in dieses Verzeichnis als letzte eine solche Option.

Der GCC cpp sucht seine Einfügeverzeichnisse in Ordnung, wenn es eine Header-Datei in einem früheren Verzeichnis findet es es verwendet wird. Ansonsten wird es schließlich die Null-Länge-Datei finden, und glücklich sein.

Ich nehme an, dass andere CPP-Implementierungen auch Verzeichnisse in der Reihenfolge suchen ihre umfassen angegeben.

Ich hatte etwas ähnliches für das Symbian OS zu tun. Dies ist, wie ich es tat: können sagen, Sie liegt vor, wenn die Datei „file_strange.h“ überprüfen wollen, und Sie wollen einige Header oder einen Link zu einigen Bibliotheken schließen auf die Existenz dieser Datei abhängig.

Creat zuerst eine kleine Batch-Datei für die Existenz dieser Datei zu überprüfen.

autoconf ist gut, aber ein über für viele kleine Projekte töten.

---------- check.bat

@echo off

IF EXIST [\epoc32\include\domain\middleware\file_strange] GOTO NEW_API
GOTO OLD_API
GOTO :EOF

:NEW_API
echo.#define NEW_API_SUPPORTED>../inc/file_strange_supported.h
GOTO :EOF

:OLD_API
echo.#define OLD_API_SUPPORTED>../inc/file_strange_supported.h
GOTO :EOF

---------- check.bat Ende

Dann habe ich eine gnumake Datei

---------- checkmedialist.mk

do_nothing :
    @rem do_nothing

MAKMAKE : 
        check.bat

BLD : do_nothing

CLEAN : do_nothing

LIB : do_nothing

CLEANLIB : do_nothing

RESOURCE : do_nothing

FREEZE : do_nothing

SAVESPACE : do_nothing

RELEASABLES : do_nothing

FINAL : do_nothing

---------- check.mk Ende

die check.mk Datei in Ihrem bld.inf Datei enthalten, müssen sie vor Ihrer MMP-Dateien sein

PRJ_MMPFILES
gnumakefile checkmedialist.mk

jetzt bei der Kompilierung der Datei file_strange_supported.h wird ein entsprechendes Flag gesetzt hat. Sie können diesen Flag in Ihren CPP-Dateien verwenden, oder sogar in der mmp-Datei zum Beispiel in mmp

#include "../inc/file_strange_supported.h"
#ifdef NEW_API_SUPPORTED
LIBRARY newapi.lib
#else
LIBRARY oldapi.lib
#endif

und in CPP

#include "../inc/file_strange_supported.h"
#ifdef NEW_API_SUPPORTED
CStrangeApi* api = Api::NewLC();
#else
// ..
#endif

Im Gegensatz zu einigen Ansprüchen hier und im Internet, wird Visual Studio 2015 nicht die __has_include Funktion unterstützen - zumindest nach meiner Erfahrung. Getestet mit Update 3.

Die Gerüchte von der Tatsache, haben ergeben, dass VS 2017 auch als „Version 15“ bezeichnet wird; VS 2015 wird stattdessen als „Version 14“. Unterstützung für das Feature scheint mit "Visual Studio 2017 Version 15.3" offiziell eingeführt wurde.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top