IT Share you

C 전처리기를 사용하여 파일이 있는지 확인할 수 있습니까?

shareyou 2020. 11. 29. 12:39
반응형

C 전처리기를 사용하여 파일이 있는지 확인할 수 있습니까?


저는 서로 다른 C ++ 컴파일러를 사용하여 서로 다른 운영 체제에서 실행되는 수많은 프로젝트에서 코드를 공유하는 매우 큰 코드베이스 (읽기 : 수천 개의 모듈)를 가지고 있습니다. 말할 필요도없이, 빌드 프로세스를 유지하는 것은 꽤 힘든 일이 될 수 있습니다.

코드베이스에는 #includes파일이 현재 폴더에 존재하지 않는 경우 전처리 기가 확실하게 무시하도록 만드는 방법이있는 경우 코드를 실질적으로 정리하는 여러 위치가 있습니다 . 누구든지 그것을 달성하는 방법을 알고 있습니까?

현재, 우리 는 공유 파일에서 #ifdef주위를 사용하고 #include, 프로젝트에 #include존재 하는지 여부를 # 정의하는 두 번째 프로젝트 특정 파일을 사용합니다 . 이것은 작동하지만 추악합니다. 사람들은 종종 프로젝트에서 파일을 추가하거나 제거 할 때 정의를 올바르게 업데이트하는 것을 잊습니다. 이 파일을 최신 상태로 유지하기 위해 사전 빌드 도구를 작성하려고 생각했지만 전처리기로이를 수행하는 플랫폼 독립적 인 방법이 있다면 대신 그렇게하는 것이 좋습니다. 어떤 아이디어?


일반적으로이 작업은 파일 포함을 시도 할 때 전처리기를 실행하는 스크립트를 사용하여 수행됩니다. 전처리 기가 오류를 반환하는지 여부에 따라 스크립트는 생성 된 .h 파일을 적절한 #define (또는 #undef)으로 업데이트합니다. bash에서 스크립트는 다음과 같이 모호하게 보일 수 있습니다.

cat > .test.h <<'EOM'
#include <asdf.h>
EOM
if gcc -E .test.h
 then
  echo '#define HAVE_ASDF_H 1' >> config.h
 else 
  echo '#ifdef HAVE_ASDF_H' >> config.h
  echo '# undef HAVE_ASDF_H' >> config.h
  echo '#endif' >> config.h
 fi

이와 같이 이식성 검사를 수행하기위한 꽤 철저한 프레임 워크는 autoconf 입니다.


작은 업데이트

일부 컴파일러는 __has_include ( header-name ).

확장이 C ++ 17 표준 ( P0061R1 ) 에 추가되었습니다 .

컴파일러 지원

  • 그 소리
  • 5.X의 GCC
  • VS2015 업데이트 2의 Visual Studio (?)

예 (clang 웹 사이트에서) :

// Note the two possible file name string formats.
#if __has_include("myinclude.h") && __has_include(<stdint.h>)
# include "myinclude.h"
#endif

출처


누락 된 헤더에 대한 특수 폴더를 만들고 해당 폴더를 마지막으로 검색하도록 만듭니다
(즉, 컴파일러 특정- "INCLUDES"환경 변수의 마지막 항목 등).

그런 다음 header1.h가 누락 될 수있는 경우 해당 폴더에 스텁을 만듭니다.

header1.h :

#define header1_is_missing

이제 언제든지 쓸 수 있습니다.

#include <header1.h>
#ifdef header1_is_missing

   // there is no header1.h 

#endif

전 처리기 자체는 파일의 존재를 식별 할 수 없지만 빌드 환경을 사용하여 식별 할 수 있습니다. 저는 대부분 make에 익숙합니다. make 파일에서 다음과 같은 작업을 수행 할 수 있습니다.

ifdef $(test -f filename && echo "present")
  DEFINE=-DFILENAME_PRESENT
endif

물론 VisualStudio와 같은 다른 빌드 환경에서 이와 유사한 것을 찾아야하지만, 이것이 존재한다고 확신합니다.


현재 디렉터리에있는 파일의 이름을 나타내는 #defines 목록을 포함하는 포함 파일을 생성하는 사전 빌드 단계를 실행할 수 있습니다.

#define EXISTS_FILE1_C
#define EXISTS_FILE1_H
#define EXISTS_FILE2_C

그런 다음 소스 코드 내에서 해당 파일을 포함하면 소스에서 EXISTS_*정의를 테스트하여 파일이 있는지 여부를 확인할 수 있습니다 .


내가 아는 한 cpp에는 파일의 존재에 관한 지시문이 없습니다.

여러 플랫폼에서 동일한 make를 사용하는 경우 Makefile의 약간의 도움으로이 작업을 수행 할 수 있습니다. Makefile에서 파일의 존재를 감지 할 수 있습니다.

foo.o: foo.c
    if [ -f header1.h ]; then CFLAGS+=-DHEADER1_INC

@Greg Hewgill이 언급했듯이 #include를 조건부로 만들 수 있습니다.

#ifdef HEADER1_INC
#include <header1.h>
#endif

또 다른 가능성 : 선택적으로 포함하려는 모든 헤더의 길이가 0 인 버전으로 디렉토리를 어딘가에 채 웁니다. 이 디렉토리에 마지막 옵션 으로 -I 인수를 전달하십시오 .

GCC cpp는 이전 디렉토리에서 헤더 파일을 찾으면이를 사용할 포함 디렉토리를 순서대로 검색합니다. 그렇지 않으면 결국 길이가 0 인 파일을 찾고 만족할 것입니다.

다른 cpp 구현도 지정된 순서대로 포함 디렉토리를 검색한다고 가정합니다.


I had to do something similar for the Symbian OS. This is how i did it: lets say you want to check if the file "file_strange.h" exists and you want to include some headers or link to some libraries depending on the existance of that file.

first creat a small batch file for checking the existence of that file.

autoconf is good but an over kill for many small projects.

----------check.bat

@echo off

IF EXIST [\epoc32\include\domain\middleware\file_strange] GOTO NEW_API
GOTO OLD_API
GOTO :EOF

:NEW_API
echo.#define NEW_API_SUPPORTED>../inc/file_strange_supported.h
GOTO :EOF

:OLD_API
echo.#define OLD_API_SUPPORTED>../inc/file_strange_supported.h
GOTO :EOF

----------check.bat ends

then i created a gnumake file

----------checkmedialist.mk

do_nothing :
    @rem do_nothing

MAKMAKE : 
        check.bat

BLD : do_nothing

CLEAN : do_nothing

LIB : do_nothing

CLEANLIB : do_nothing

RESOURCE : do_nothing

FREEZE : do_nothing

SAVESPACE : do_nothing

RELEASABLES : do_nothing

FINAL : do_nothing

----------check.mk ends

include the check.mk file in your bld.inf file, it MUST be before your MMP files

PRJ_MMPFILES
gnumakefile checkmedialist.mk

now at compile time the file file_strange_supported.h will have an appropriate flag set. you can use this flag in your cpp files or even in the mmp file for example in mmp

#include "../inc/file_strange_supported.h"
#ifdef NEW_API_SUPPORTED
LIBRARY newapi.lib
#else
LIBRARY oldapi.lib
#endif

and in .cpp

#include "../inc/file_strange_supported.h"
#ifdef NEW_API_SUPPORTED
CStrangeApi* api = Api::NewLC();
#else
// ..
#endif

Contrary to some claims here and on the internet, Visual Studio 2015 does NOT support the __has_include feature - at least according to my experience. Tested with Update 3.

The rumors may have arisen from the fact that VS 2017 is also referred to as "Version 15"; VS 2015 is instead referred to as "Version 14". Support for the feature seems to have been officially introduced with "Visual Studio 2017 Version 15.3".

참고URL : https://stackoverflow.com/questions/142877/can-the-c-preprocessor-be-used-to-tell-if-a-file-exists

반응형