Frage

Ich bin mit GCC; __FILE__ gibt die aktuelle gesamten Pfad und den Namen der Quelldatei: /path/to/file.cpp. Gibt es eine Möglichkeit nur den Namen file.cpp der Datei (ohne Pfad) während der Kompilierung zu bekommen? Ist es möglich, dies in einer tragbaren Weise zu tun? Meta-Programmierung Strings können Vorlage angewendet werden?

Ich verwende diese in einem Fehlerprotokollierung Makro. Ich meine Quelle ist nicht wollen vollständigen Pfad, der seinen Weg in die ausführbare wirklich.

War es hilfreich?

Lösung

Wenn Sie ein Programm make verwenden, sollten Sie in der Lage sein, die Dateinamen vorher munge und als Makro übergeben gcc in Ihrem Programm verwendet werden.

In Ihrer Make-Datei, ändern Sie die Zeile:

file.o: file.c
    gcc -c -o file.o src/file.c

zu:

file.o: src/file.c
    gcc "-D__MYFILE__=\"`basename $<`\"" -c -o file.o src/file.c

Dies ermöglicht es Ihnen __MYFILE__ in Ihrem Code statt __FILE__ zu verwenden.

Die Verwendung von Basisnamen der Quelldatei ($ <) bedeutet, dass Sie es in verallgemeinerten Regeln wie „.c.o“ verwenden können.

Der folgende Code zeigt, wie es funktioniert.

Datei-Make-Datei:

mainprog: main.o makefile
    gcc -o mainprog main.o

main.o: src/main.c makefile
    gcc "-D__MYFILE__=\"`basename $<`\"" -c -o main.o src/main.c

Datei src / main.c:

#include <stdio.h>

int main (int argc, char *argv[]) {
    printf ("file = %s\n", __MYFILE__);
    return 0;
}

Ausführen von der Shell:

pax@pax-desktop:~$ mainprog
file = main.c
pax@pax-desktop:~$

Beachten Sie die "file =" Zeile, die nur die Basisnamen der Datei enthält, nicht die dirname.

Andere Tipps

Betrachten Sie diese einfache Quellcode:

#include <stdio.h>
int main(void)
{
    puts(__FILE__);
    return(0);
}

Unter Solaris mit GCC 4.3.1, wenn ich kompilieren diese mit:

gcc -o x x.c && ./x

ist der Ausgang 'x.c' Wenn ich kompilieren mit:

gcc -o x $PWD/x.c && ./x

dann __FILE__ Karten auf den vollständigen Pfad ( '/work1/jleffler/tmp/x.c'). Wenn ich kompilieren mit:

gcc -o x ../tmp/x.c && ./x

dann __FILE__ Karten zu '../tmp/x.c'.

Also, im Grunde ist __FILE__ der Pfadname der Quelldatei. Wenn Sie mit dem Namen, den Sie in dem Objekt sehen will bauen, ist alles gut.

Wenn das nicht möglich ist (aus irgendeinem Grund), dann werden Sie in die Korrekturen bekommen müssen von anderen vorgeschlagen.

Ich weiß nicht, von einer direkten Art und Weise. Sie könnten verwenden:

#line 1 "filename.c"

an der Spitze der Quelldatei den Wert von __FILE__ zu setzen, aber ich bin nicht sicher, dass das ist viel besser als harte Kodierung es. oder einfach nur einen #define mit Ihrem eigenen Makros zu erstellen.

Eine weitere Option könnte sein, den Namen von Ihrem Makefile übergibt mit -D und $ (shell base $ <)

Edit:. Wenn Sie eine #define oder die -D-Option verwenden, sollten Sie Ihre eigenen neuen Namen erstellen und versuchen, nicht __FILE__ neu zu definieren

Was ist Ihre Fehlerprotokollierung Makro tun? Ich würde irgendwann nehme an dem Makro schließlich eine Funktion irgendeiner Art, um die Protokollierung zu tun nennt, warum nicht die Funktionsleiste von der Pfadkomponente zur Laufzeit aufgerufen hat?

#define LOG(message) _log(__FILE__, message)

void _log(file, message)
{
  #ifndef DEBUG
  strippath(file); // in some suitable way
  #endif

  cerr << "Log: " << file << ": " << message; // or whatever
}

Da Sie CMake markiert, hier ist eine saubere Lösung zu Ihrem CMakeLists.txt hinzu: (Kopiert von http://www.cmake.org/pipermail/cmake/ 2011 Dezember / 048281.html ). (Anmerkung: einige Compiler nicht pro-Datei COMPILE_DEFINITIONS unterstützen, aber es funktioniert mit gcc)

set(SRCS a/a.cpp b/b.cpp c/c.cpp d/d.cpp)

foreach(f IN LISTS SRCS)
 get_filename_component(b ${f} NAME)
 set_source_files_properties(${f} PROPERTIES
  COMPILE_DEFINITIONS "MYSRCNAME=${b}")
endforeach()

add_executable(foo ${SRCS})

Hinweis: Für meine Anwendung, die ich benötigen, um die Dateinamen Zeichenfolge wie folgt zu entkommen:

COMPILE_DEFINITIONS "MYSRCNAME=\"${b}\"")

Sie könnten in der Lage, es mit Metaprogrammierung zu tun, aber es gibt keine integrierte Möglichkeit, es zu tun.

EDIT: Hm, Korrektur. Nach einer Seite sah ich nur verwendet GCC den Pfad, den es für die Datei angegeben wird. Wenn es den vollständigen Namen gegeben hat, wird es es einzubetten; wenn es nur einen relativen gegeben hat, wird es einbetten nur das. Ich habe es nicht versucht, mich aber.

Unter der Idee von Glomek, kann es wie folgt automatisiert werden:

Die Quelldatei x.c

#line 1 MY_FILE_NAME
#include <stdio.h>

int main(void)
{
    puts(__FILE__);
    return(0);
}

Compilation Linie (die einfachen Anführungszeichen außerhalb der doppelten Anführungszeichen passen):

gcc -DMY_FILE_NAME='"abcd.c"' -o x x.c

Der Ausgang ist 'abcd.c'.

Sie können __FILE__ in einen String zuweisen und dann _splitpath () aufrufen, um die Stücke aus ihm heraus zu reißen. Dies könnte ein Fenster / MSVC-only Lösung sein, ehrlich ich weiß es nicht.

Ich weiß, Sie wurden für eine Kompilierung-Lösung suchen, und das ist eine Laufzeit Lösung, aber ich dachte, da Sie die Dateinamen wurden mit tun (vermutlich Laufzeit) der Fehlerprotokollierung, könnte dies eine einfache unkomplizierte Art und Weise sein, zu bekommen, was Sie brauchen.

Sie können nehmen __FILE__ und die Streifen aus dem Teil des Weges wollen Sie nicht (programmatisch). Wenn basedir erfüllt Ihre Bedürfnisse, dann fein. Andernfalls Quelle dir Wurzel aus dem Build-System erhalten, und der Rest sollte machbar sein.

Wir waren gerade das gleiche Problem; eine andere Lösung gefunden, dachte nur, ich es teilen würde:

In einer Header-Datei in all meinen anderen Dateien enthalten:

static char * file_bname = NULL;
#define __STRIPPED_FILE__   (file_bname ?: (file_bname = basename(__FILE__)))

Hope dies ist nützlich, um jemand anderes auch:)

kann nur programmatisch durchgeführt werden.

vielleicht ist nützlich ...

filename = __FILE__
len  = strlen(filename)

char *temp = &filename[len -1]
while(*temp!= filename)
    if(*temp == '\') break;

Es ist leicht, mit cmake.

DefineRelativeFilePaths.cmake

function (cmake_define_relative_file_paths SOURCES)
  foreach (SOURCE IN LISTS SOURCES)
    file (
      RELATIVE_PATH RELATIVE_SOURCE_PATH
      ${PROJECT_SOURCE_DIR} ${SOURCE}
    )

    set_source_files_properties (
      ${SOURCE} PROPERTIES
      COMPILE_DEFINITIONS __RELATIVE_FILE_PATH__="${RELATIVE_SOURCE_PATH}"
    )
  endforeach ()
endfunction ()

Irgendwo in CMakeLists.txt

set (SOURCES ${SOURCES}
  "${CMAKE_CURRENT_SOURCE_DIR}/common.c"
  "${CMAKE_CURRENT_SOURCE_DIR}/main.c"
)

include (DefineRelativeFilePaths)
cmake_define_relative_file_paths ("${SOURCES}")

cmake .. && make clean && make VERBOSE=1

cc ... -D__RELATIVE_FILE_PATH__="src/main.c" ... -c src/main.c

Das ist es. Jetzt können Sie ziemlich Log-Meldungen machen.

#define ..._LOG_HEADER(target) \
  fprintf(target, "%s %s:%u - ", __func__, __RELATIVE_FILE_PATH__, __LINE__);
  

func src / main.c: 22 - mein Fehler

PS Es ist besser, in config.h.in declear -> config.h

#ifndef __RELATIVE_FILE_PATH__
#define __RELATIVE_FILE_PATH__ __FILE__
#endif

So Ihre Linter Wan't regen von Fehlern liefern.

Sie können verwendet werden:

bool IsDebugBuild()
{
    return !NDEBUG;
}

Oder Sie NDEBUG in Ihrem Makro verwenden könnten, um diese Dateipfade zu aktivieren / deaktivieren.

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