문제

GCC를 사용하고 있습니다. __file__ 현재 소스 파일의 전체 경로 및 이름을 반환합니다. /path/to/file.cpp. 파일 이름 만 얻는 방법이 있습니까? file.cpp 컴파일 시간에 (경로없이)? 휴대용으로 이것을 할 수 있습니까? 템플릿 메타 프로그래밍을 문자열에 적용 할 수 있습니까?

오류 로깅 매크로에서 이것을 사용하고 있습니다. 나는 내 소스의 전체 경로가 실행 파일로 들어가는 것을 정말로 원하지 않습니다.

도움이 되었습니까?

해결책

Make 프로그램을 사용하는 경우 프라이팬을 미리 MUNGE로하여 프로그램에서 사용할 수있는 매크로로 GCC로 전달할 수 있어야합니다.

makefile에서 선을 변경하십시오.

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

에게:

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

이것은 당신이 사용할 수있게합니다 __MYFILE__ 대신 코드에서 __FILE__.

소스 파일 ($ <)의베이스 이름을 사용한다는 것은 ".co"와 같은 일반 규칙에서 사용할 수 있음을 의미합니다.

다음 코드는 작동 방식을 보여줍니다.

파일 makefile :

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

파일 src/main.c :

#include <stdio.h>

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

쉘에서 실행 :

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

Dirname이 아닌 파일의베이스 이름 만 포함하는 "file ="라인에 주목하십시오.

다른 팁

이 간단한 소스 코드를 고려하십시오.

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

Solaris에서 GCC 4.3.1을 사용하여 다음을 사용하면 다음을 컴파일합니다.

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

출력은 'x.c'내가 그것을 사용하여 컴파일하면 :

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

그런 다음 __file__는 전체 경로에 맵핑됩니다 ( '/work1/jleffler/tmp/x.c'). 사용하여 컴파일하는 경우 :

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

그런 다음 __file__지도../tmp/x.c'.

따라서 기본적으로 __file__는 소스 파일의 경로 이름입니다. 객체에서보고 싶은 이름으로 빌드하면 모든 것이 좋습니다.

그것이 불가능하다면 (어떤 이유로 든) 다른 사람들이 제안한 수정 사항에 들어가야합니다.

나는 직접적인 방법을 모른다. 당신은 사용할 수 있습니다 :

#line 1 "filename.c"

소스 파일의 상단에서 __FILE__, 그러나 나는 그것이 하드 코딩하는 것보다 훨씬 낫다고 확신하지 못한다. 또는 #define을 사용하여 자신의 매크로를 만듭니다.

또 다른 옵션은 -d 및 $ (Shell Basename $ <)를 사용하여 makefile에서 이름을 전달하는 것입니다.

편집 : #define 또는 -d 옵션을 사용하는 경우 자신만의 새 이름을 만들고 재정의하지 않아야합니다. __FILE__.

오류 로깅 매크로는 무엇을합니까? 나는 매크로가 결국 로깅을하기 위해 어떤 종류의 함수를 호출한다고 가정 할 것입니다. 왜 런타임에서 경로 구성 요소에서 호출 된 함수를 제거하지 않겠습니까?

#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
}

cmake에 태그가 지정된 이후, cmakelists.txt에 추가 할 수있는 깔끔한 솔루션이 있습니다. http://www.cmake.org/pipermail/cmake/2011-december/048281.html ). (참고 : 일부 컴파일러는 파일 별 compile_definitions를 지원하지 않지만 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})

참고 : 내 응용 프로그램의 경우 다음과 같은 파일 이름 문자열을 피해야했습니다.

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

템플릿 Metaprogramming으로 수행 할 수는 있지만 내장 방법은 없습니다.

편집 : HM, 수정. 에 따르면 방금 본 한 페이지, GCC는 파일에 주어진 경로를 사용합니다. 전체 이름이 주어지면 그것을 포함시킬 것입니다. 그것이 상대적으로 만 주어지면, 그것은 단지 그것을 포함시킬 것입니다. 나는 그것을 직접 시도하지 않았다.

Glomek의 아이디어를 가져 오면 다음과 같이 자동화 할 수 있습니다.

소스 파일 XC

#line 1 MY_FILE_NAME
#include <stdio.h>

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

컴파일 라인 (이중 인용구 외부의 단일 따옴표를 조심하십시오) :

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

출력은 'abcd.c'.

당신은 할당 할 수 있습니다 __FILE__ 문자열로, _splitpath ()를 호출하여 조각을 찢어 버립니다. 이것은 Windows/MSVC 전용 솔루션 일 수 있습니다. 솔직히 모르겠습니다.

나는 당신이 컴파일 타임 솔루션을 찾고 있다는 것을 알고 있으며 이것은 런타임 솔루션이지만, 파일 이름을 사용하여 (아마도 런타임) 오류 로깅을했기 때문에 이것은 당신을 얻는 간단한 간단한 방법 일 수 있습니다. 필요한 것.

당신은 __file__와 스트립을 원하지 않는 경로의 일부에서 제거 할 수 있습니다 (프로그래밍적으로). 기반이 당신의 요구를 충족 시키면 괜찮습니다. 그렇지 않으면 빌드 시스템에서 소스 딥 루트를 가져 오면 나머지는 가능해야합니다.

방금 같은 문제를 겪었습니다. 다른 결의안을 찾았고 그냥 공유 할 것이라고 생각했습니다.

다른 모든 파일에 포함 된 헤더 파일에서 :

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

이것이 다른 사람에게도 유용하기를 바랍니다 :)

프로그래밍 방식으로 만 수행 할 수 있습니다.

아마도 이것은 유용 할 것입니다 ...

filename = __FILE__
len  = strlen(filename)

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

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 ()

어딘가 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

그게 다야. 이제 예쁜 로그 메시지를 만들 수 있습니다.

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

func src/main.c : 22- 내 오류

추신 : 쇠약 해지는 것이 좋습니다 config.h.in -> config.h

#ifndef __RELATIVE_FILE_PATH__
#define __RELATIVE_FILE_PATH__ __FILE__
#endif

그래서 당신의 린터는 오류의 비를 제공하지 않습니다.

당신은 사용할 수 있습니다 :

bool IsDebugBuild()
{
    return !NDEBUG;
}

또는 매크로에서 ndebug를 사용하여 해당 파일 경로를 켜거나 끕니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top