Getting base name of the source file at compile time

后端 未结 14 2139
有刺的猬
有刺的猬 2020-12-14 10:07

I\'m using GCC; __FILE__ returns the current source file\'s entire path and name: /path/to/file.cpp. Is there a way to get just the file\'s name file.cpp<

相关标签:
14条回答
  • 2020-12-14 10:23

    Could be done ONLY programmatically.

    maybe this is useful...

    filename = __FILE__
    len  = strlen(filename)
    
    char *temp = &filename[len -1]
    while(*temp!= filename)
        if(*temp == '\') break;
    
    0 讨论(0)
  • 2020-12-14 10:24

    I don't know of a direct way. You could use:

    #line 1 "filename.c"
    

    at the top of the source file to set the value of __FILE__, but I'm not sure that that's much better than hard coding it. or just using a #define to create your own macro.

    Another option might be to pass the name from your Makefile using -D and $(shell basename $<)

    Edit: If you use a #define or the -D option, you should create your own new name and not try to redefine __FILE__.

    0 讨论(0)
  • 2020-12-14 10:27

    Taking the idea from Glomek, it can be automated like this:

    Source file x.c

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

    Compilation line (beware the single quotes outside the double quotes):

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

    The output is 'abcd.c'.

    0 讨论(0)
  • 2020-12-14 10:30

    Since you tagged CMake, here's a neat solution to add to your CMakeLists.txt: (copied from http://www.cmake.org/pipermail/cmake/2011-December/048281.html ). (Note : some compilers don't support per-file COMPILE_DEFINITIONS ! but it works with 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})
    

    Note : For my application I needed to escape the filename string like this:

    COMPILE_DEFINITIONS "MYSRCNAME=\"${b}\"")
    
    0 讨论(0)
  • 2020-12-14 10:31

    It is easy with 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 ()
    

    Somewhere 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
    

    That's it. Now you can make pretty log messages.

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

    func src/main.c:22 - my error

    PS It is better to declear in config.h.in -> config.h

    #ifndef __RELATIVE_FILE_PATH__
    #define __RELATIVE_FILE_PATH__ __FILE__
    #endif
    

    So your linter wan't provide rain of errors.

    0 讨论(0)
  • 2020-12-14 10:33

    You might be able to do it with template metaprogramming, but there's no built-in way to do it.

    EDIT: Hm, correction. According to one page I just saw, GCC uses the path that it's given for the file. If it's given the full name, it'll embed it; if it's only given a relative one, it'll only embed that. I haven't tried it myself though.

    0 讨论(0)
提交回复
热议问题