Interpretation relativer Include-Pfade
-
Angenommen, ich gebe dem Compiler beim Aufruf zwei Include-Pfade:
-Ic:\einelib\include -Inochnelib\include
Hiermit wird die Datei
d:\programm\code.cpp
übersetzt und dort findet sich ein
#include <ein_header.hpp>
Dieser wird gefunden als:
c:\einelib\include\ein_header.hpp
Innerhalb dieses Headers findet sich:
#include <zweiter_header.hpp>
und zweiter_header.hpp ist im Pfad
c:\einelib\include
nicht zu finden, so dass nun der relative Include-Pfad (nochnelib\include) versucht werden muss. Hierzu muss natürlich der relative Pfad absolut gemacht werden.
Meine Frage ist, welche Vorgehensweise sieht der Standard hier vor? Mir fallen dazu zwei Möglichkeinten ein:
1.) Der relative Pfad wird anhand des Pfades der aktuell gelesenen Datei absolut gemacht. Das ist
c:\einelib\include\ein_header.hpp
so dass also das Include als
c:\einelib\include\nochnelib\include\zweiter_header.hpp
interpretiert wird.
2.) Der relative Pfad wird anhand der ursprünglich an den Compiler übergebenen Datei aufgelöst. Dies ist
d:\programm\code.cpp
so dass als das Include als
d:\programm\nochnelib\include\zweiter_header.hpp
aufgelöst wird.
Weiß jemand, was der Standard sagt?
Stefan.
-
[Standard]
A #include directive shall identify a header or source file that can be processed by the implementation.A preprocessing directive of the form
# include <h-char-sequence> new-line
searches a sequence of implementation-defined places for a header identified uniquely by the specified sequence between the < and > delimiters, and causes the replacement of that directive by the entire contents of the header. How the places are specified or the header identified is implementation-defined.A preprocessing directive of the form
# include "q-char-sequence" new-line
causes the replacement of that directive by the entire contents of the source file identified by the specified sequence between the " delimiters. The named source file is searched for in an implementation-defined manner. If this search is not supported, or if the search fails, the directive is reprocessed as if it read
# include <h-char-sequence> new-line
with the identical contained sequence (including > characters, if any) from the original directive.[/Standard]
Zusammenfassung: Der Standard sagt, dass es implementierungsabhängig ist
-
SeppJ schrieb:
Zusammenfassung: Der Standard sagt, dass es implementierungsabhängig ist
Das hatte ich befürchtet
Trotzdem danke!Stefan.
-
Bei den meisten Compilern dürftest du mit dem von dir beschriebenen Fall kein Problem haben. Interessant wird es aber, falls der Dateiname nicht mehr eindeutig sein sollte - dann weiß ich echt nicht, welche Datei zuerst genommen würde.
-
SeppJ schrieb:
Bei den meisten Compilern dürftest du mit dem von dir beschriebenen Fall kein Problem haben. Interessant wird es aber, falls der Dateiname nicht mehr eindeutig sein sollte - dann weiß ich echt nicht, welche Datei zuerst genommen würde.
Ich frage mich nur, welche Konsequenzen man aus dieser Unbestimmtheit ziehen sollte. Keine relativen Pfade mehr mit "-I" angeben? Das Team darauf festnageln, alle verwendeten Libs und auch die Sourcen des Projekts in einheitlichen Pfaden zu installieren? Beides? Oder es einfach darauf ankommen zu lassen?
Das ist jetzt kein Problem, das mir unter den Nägeln brennt. Aber manchmal kann ich nur den Kopf schütteln, was im Rahmen einer Standardisierung alles undefiniert gelassen wird.
Tja...
Stefan.
-
Ich verstehe die Frage beim besten Willen nicht was du dem Compiler mitangibst wie er die Inkludes auflösen soll ich doch ganz klar compilerabhängig, d.h. du musst für jeden Compiler getrennt entscheiden, oder du benutzt einfach absolute Pfade.
Allerdings wird ein normaler Compiler alle mit -I übergebenen Pfade einfach in absolute übersetzen, ausgehend von dem Arbeitsverzeichnis in dem du den Compiler aufgerufen hast (die Pfade sind nämlich für den Compile bestimmt nicht für dein Programm!!).
-
DStefan schrieb:
Aber manchmal kann ich nur den Kopf schütteln, was im Rahmen einer Standardisierung alles undefiniert gelassen wird.
Das liegt daran, dass der C++-Standard die Sprache C++ beschreibt und nicht, wie man einen Compiler baut. Schließlich soll die Sprache nicht an den Feinheiten von bestimmten Dateisystemen festgemacht sein, denn C++ soll ja auch auf Systemen ohne das Konzept von "Pfaden" funktionieren. Die Möglichkeit, implementierungsabhängige Includes zuzulassen, ist ein guter Kompromiss, da ein Compilerhersteller so seinen Compiler an das Leistungsvermögen der zielplattform anpassen kann.
-
SeppJ schrieb:
DStefan schrieb:
Aber manchmal kann ich nur den Kopf schütteln, was im Rahmen einer Standardisierung alles undefiniert gelassen wird.
Das liegt daran, dass der C++-Standard die Sprache C++ beschreibt und nicht, wie man einen Compiler baut. Schließlich soll die Sprache nicht an den Feinheiten von bestimmten Dateisystemen festgemacht sein, denn C++ soll ja auch auf Systemen ohne das Konzept von "Pfaden" funktionieren. Die Möglichkeit, implementierungsabhängige Includes zuzulassen, ist ein guter Kompromiss, da ein Compilerhersteller so seinen Compiler an das Leistungsvermögen der zielplattform anpassen kann.
Ich kenne dieses Argument, aber es zieht bei mir nicht. In dieser Hinsicht bin ich vielleicht zu sehr Pragmatiker.
Es ist ja durchaus möglich (und wird es in anderen Sprachen nicht auch so gemacht?), Bedingungen oder Stufen zu definieren nach dem Motto: "Wenn eine Umgebung Pfade (Threads, GUIs usw.) unterstützt, soll ein Compiler soundso vorgehen oder die Standardbibliothek dies und das unterstützen - und nur dann ist es ein Compiler gemäß Standard, Stufe 2". Sieh dir Boost an und du weißt, dass sowas funktioniert.
Ich habe das Gefühl, dass C++ aufgrund solcher selbst auferlegten Beschränkungen (die aus meiner Sicht zudem nicht mehr zeitgemäß sind) mehr und mehr ins Hintertreffen gerät. Wenn du für ein Projekt z.B. Java wählst, kannst du mit dem, was standardmäßig zur Sprache gehört wahnsinnig viel anfangen. Wählst du C++, musst du dir in den allermeisten Fällen erst einmal Gedanken darüber machen, wie du Dinge hinkriegst, die heutzutage einfach zum Alltag gehören. Ich bedaure das sehr, denn niemand ist ein größerer C++-Fan als ich.
Aber das ist wohl ziemlich OT. Hoffentlich habe ich jetzt nicht eine Lawine losgetreten
Stefan.
-
Hallo DStefan,
stimme dir voll zu - mich nerven auch die ganzen "undefined" und "implementation-dependant" im C++-Standard. Denn gerade beim Austausch von Compilern bzw. beim Übersetzen auf einer anderen Plattform immer wieder Ärger zu haben behindert die effektive Entwicklung.
Mich stört insbesondere, daß es bei den Compilern keine Option gibt, welche die "undefined" bzw. "implementation-dependant" zumindestens als Warnungen anzeigt (mir wäre sogar eine strikte Option am liebsten).P.S: Seit einigen Jahren programmiere ich auch in C#, und dort gibt es keine Warnungen, sondern nur Fehler. Lieber einmal auf einen Fehler hingewiesen werden, als irgendwann zur Laufzeit ein undefiniertes Verhalten zu haben (mal klappt's, dann wieder nicht und beim nächsten Mal ist es wider ganz anderes)
-
Mir persönlich wären harte Fehler auch lieber, als Verhalten, dass man unter Umständen gar nicht bemerkt. Ich kann dem einfach nichts abringen, dass "undefinierte Programme" laufen. Meinetwegen soll es einen Laufzeitfehler geben, aber nichts undefiniertes, dass manchmal nix passiert und irgendwann ein Fehler. Das ist schon recht mühsam.
-
Kannst du mir bitte ein Beispiel geben, bei dem du mit der Konvertierung von standardkonformen C++ auf eine andere Plattform ein Problem hattest? Ich entwickle meine Programme für vier verschiedene Plattformen und hatte noch nie irgendein noch so kleines Problem dabei.
-
SeppJ schrieb:
Kannst du mir bitte ein Beispiel geben, bei dem du mit der Konvertierung von standardkonformen C++ auf eine andere Plattform ein Problem hattest? Ich entwickle meine Programme für vier verschiedene Plattformen und hatte noch nie irgendein noch so kleines Problem dabei.
Das kann ich leider nicht, da dieses Problem in meiner Praxis auch noch nie aufgetreten ist. Was allerdings womöglich daran liegt, dass ich immer versucht habe, es gar nicht auftreten zu lassen. Meine Argumente zu "-I" sind immer absolute Pfade oder sowas wie "/library/includes", was unter Windows ja nur einen Pfad relativ zum aktuellen Laufwerk angibt.
Die Frage stellt sich mir im Moment, da ich eine Art Mini-Make schreibe. Ich möchte mich intensiver in Boost einarbeiten und brauchte halt irgend ein (möglichst überschaubares) Projekt. Tja - und jetzt muss ich, um Dependencies rauszufinden, halt Include-Pfade möglichst so auflösen, wie's der Compiler macht.
Sorry, wenn ich dir mit meiner Frage schlaflose Nächte bereitet habe
Stefan.
-
Es geht ja gerade um die Frage, ob ein C++ Programm standardkonform ist.
Nur weil es ein Compiler schluckt, kann es bei einem anderen Compiler zu Fehlern führen bzw. erst zur Laufzeit undefiniertes Verhalten hervorrufen.Ich selber kenne mich gut genug mit C++ aus, um die (meisten) Fallstricke zu umgehen, jedoch habe ich schon diverse Programme von anderen Leuten gesehen (vergleiche hier nur im Forum die MS und gcc-Unterschiede), welche eben nicht so einfach zu portieren sind. Und dann wäre es eben besser, die Compiler würden noch mehr Fehler werfen, anstatt irgenwelchen compilerspezifischen Code zu erlauben.
Und die nächsten Versionen der verschiedenen Compiler bringen dann auch wieder zu viele Unterschiede (je nachdem welche neuen Features des C++0x sie unterstützen - einige kommen dann erst ab TR2 usw.).
Für mich bedeutet eigentlich eine Standardisierung, daß sich alle daran zu halten haben und nicht, daß jeder Hersteller sein eigenes Süpplein kocht.