Wie extrahieren Sie die Quell-Dateiname ohne Pfad und suffix zur compile-Zeit?
Sowohl mithilfe von gcc mit -std=c11-und g++ - mit -std=c++14.
E. g. für eine Datei mit dem Namen src/dir/Hello.cxx
es sollte zu erweitern, um so etwas wie z.B.:
const char basename[] = "Hello";
oder
const char basename[] = getStaticBasename(__FILE__);
da, wo getStaticBasename()
ist ein makro (für C-Quellen) oder constexpr-Funktion (für C++ - Quellen) die Ergebnisse zu "Hallo".
Habe ich, um zu vermeiden Aufspaltung der string aus __FILE__
zur Laufzeit, da der Pfad und suffix muss nicht kompiliert werden, in die ausführbare Datei in keiner Weise.
Muss die Lösung sein, ohne Abhängigkeiten zu riesigen Bibliotheken wie boost.
Da ich keine makefiles, Lösungen wie diese nicht verwendet werden, in meinem Fall.
Hatte man eine Lösung für das?
Bearbeiten 2015-07-02:
- Ich habe keinen Einfluss darauf, wie der compiler und linker aufgerufen wurde (manchmal über makefile, mal von der Kommandozeile, oder einige IDE (Eclipse CDT managed machen, Crossworks, Xcode et cetera. Also die Lösung muss im code nur.
- Mein use-case ist eine Art "generic region identifier" für eine kleine Stellfläche logging-Lösung. Den code der Anwendung (die nutzt mein logger) sollte nur
#include <Joe/Logger.h>
und in den später ruft z.B.LOG_DEBUG(...)
ich werde implizit nutzen, die automatisch generierte "generic region identifier". - Meine aktuelle Lösung ist, dass der code der Anwendung zu deklarieren einer
JOE_LOG_FILE_REGION(Hello);
(nach#include <Joe/Logger.h>
) vor OrtLOG_DEBUG(...)
im code.
- C++ ist ziemlich einfach. Ich kann nicht glauben, wie es gemacht werden würde in C.
- Ich denke es ist am besten aufteilen, diese Frage in zwei, wie c++ Aussehen kann sehr unterschiedlich aufgrund der Möglichkeit der Verwendung von
constexpr
s. - Die Frage ist nicht doppelt vorhanden, weil Sie es wollen zur compile-Zeit, aber eine Antwort gibt es, was Sie brauchen:
__FILE__
makro zeigt vollständigen Pfad - Warum gehst du nicht fügen Sie Ihrem C++ - Lösung als Antwort, oder zumindest geben einige Hinweise? Ja, es antwortet nicht der C-Teil, aber es ist immer noch besser als nichts.
- Ich fürchte, mir fehlt die Zeit (und vielleicht die smarts) zusammenbringen, aber hier ist eine Umsetzung durch jemand anderes bietet die schwieriger bits (substr): "github.com/dscharrer/void/blob/master/c%2B%2B/...
- Die
makefile
Lösung angepasst werden kann, um die Befehlszeile. Nur haben einige-Skript zu bauen, Ihre Sache, oder sogar die Verwendung von einem Skript anstatt derg++
- Ich brauche eine Lösung, die unabhängig ist, wie der compiler aufgerufen wird.
- Yep, ich denke, ich werde es aufgeteilt in zwei Fragen, die für C und C++
Du musst angemeldet sein, um einen Kommentar abzugeben.
#define __FILENAME__ (__builtin_strrchr(__FILE__, '/') ? __builtin_strrchr(__FILE__, '/') + 1 : __FILE__)
oder
#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
Beispiel:
den Namen der Quelldatei ist
foo/foo1/foo2/foo3/foo4.cpp
verwenden
g++ -o foo.exe foo/foo1/foo2/foo3/foo4.cpp -std=c++11 --save-temps
zum kompilieren dieser Datei.können Sie dies sehen.
movl $.LC0+19, %edi
.LC0 + 19 ist die Adresse der Datei-name ohne Pfad und suffix__builtin_strrchr
verwendet werden bei der Initialisierung der statischen variable, weil "element-Initialisierer ist nicht konstant".#define __FILENAME__
mitconstexpr const char* basename=__FILENAME__
aber mein g++ 4.8.5 beschwert sich über eine Funktion nichtconstexpr
. es scheint also, dass diese Lösung hängt davon ab, wie der compiler-Optimierungen aktiviert.Wenn Sie gcc aus dem Ordner, in dem sich die Quelldatei befindet, erhalten Sie eine andere
__FILE__
als wenn Sie einen absoluten Pfad (D. H. ausgehändigt gcc über eine IDE).gcc test.c -otest.exe
gibt mir__FILE__
alstest.c
.gcc c:\tmp\test.c -otest.exe
gibt mir__FILE__
alsc:\tmp\test.c
.Vielleicht den Aufruf von gcc den Pfad, wo sich die Quelle befindet, ist ausreichend als work-around?
BEARBEITEN
Hier ist eine "schmutzige", aber sichere hack, die entfernt die Datei-Erweiterung im compile-Zeit. Nicht wirklich etwas, was ich empfehlen würde, aber es hat Spaß gemacht zu schreiben 🙂 So nehmen Sie es für was es Wert ist. Es funktioniert nur im C.
Die union weist ein Mitglied die groß genug ist, um den vollständigen Pfad minus-Erweiterung und null-terminator. Und es weist ein Mitglied die groß genug ist, um den vollständigen Pfad minus-Erweiterung, allerdings mit einem null-terminator.
Den Mitgliedstaaten das ist zu klein, um das volle
__FILE__
initialisiert wird mit so viel__FILE__
als passen kann. Das ist ok in C, aber nicht erlaubt in C++. Wenn__FILE__
enthälttest.c
, Mitglied der union werden nun initialisiert, enthaltentest
ohne null-terminator.Wird es aber noch werden nachgestellte Nullen nach diesem string, weil dieser hack missbraucht die Tatsache, dass die anderen EU-Mitglied wurde initialisiert, die nach den Regeln des "Aggregat/union" Initialisierung. Diese Regel zwingt die verbleibenden Artikel in der "Aggregat" initialisiert werden, als wären Sie statische Speicher Dauer, ich.e auf null. Was der Wert der null-terminator.
union { int a, b; } = { 3 }
verlassen würde 0 in der union. Sie müssen interpretiert werden im Licht der...extract die base mit dem Namen bei der Kompilierung mit keine Präprozessor-tricks und keine externe Skripte? c++14? kein problem, sir.
constexpr
es die eigene Sprache. darüber hinaus gibt es die c++ - templates... Sie sind eine andere Sprache. der Präprozessor ist eine andere Sprache.Es stellt sich heraus sehr einfach, Sie brauchen nur die
#Linie
Präprozessor-Direktive, Beispieloben in der Datei, wie es ist, wenn alle Sie wollen, ist zu verbergen der Dateiname komplett dann
funktionieren würde.
Wenn Sie nicht möchten, zu verwenden
Makefile
s, Sie können dieseDen
-xc
gcc fahne oben bedeutet (aus der gcc-Dokumentation):Wenn Sie nicht über jede Art von Skript, das Ihnen hilft, Bau die Quelle, dann gibt es keinen Weg, es zu tun, denke ich.
Auch, Sie sehen aus dem obigen Zitat der gcc-Dokumentation, dass Sie die Dateien speichern können, ohne jegliche Erweiterung, und dann kombinieren @Lundin's original Lösung mit diesem, und verwenden Sie
in diesem Fall
__FILE__
erweitern würden, um"filename_without_extension"
, und Sie würden erreichen, was Sie wollen, obwohl, müssen Sie kompilieren Sie die Datei in das gleiche Verzeichnis, in dem es lebt, weil es sonst enthalten, der Pfad zu der Datei."hello"
in der Quell-Datei (also in der#line
- Richtlinie)? Der name der Datei kann beliebig sein, nicht nurhello.cpp
.__FILE__
makro, wenn es bereits benutzt wurde.-DFILE_BASE=...
. Die Namen werden in Python/SCons so.scons
? es ist so kompliziert zu bedienen python-Werkzeuge, es ist version 3 oder 2 und alle, die cr*p... Aber ja, du hast Recht, das wäre eine perfekte Lösung, wenn die OP wollte die build-Skripte aller Art. Ich weiß nicht, wiescons
weil mein linux-Distribution hat einen Paketmanager rollte durch mein selbst, also wenn ich brauche einige neue Paket muss ich es kompilieren aus dem Quellcode, das ist ein Alptraum werden, wenn die build-tools sindscons
oderwaf
.gcc -O3 -o ${file} -DFILE_BASE="\"${file}\"" "${file}.c"
direkt, ohne Ihre Quelle durchsed
und komplizierten Sachen wie, dass.