C 프리 프로세서를 사용하여 파일이 존재하는지 알 수 있습니까?

StackOverflow https://stackoverflow.com/questions/142877

  •  02-07-2019
  •  | 
  •  

문제

C ++ 컴파일러가 다른 운영 체제에서 실행되는 수많은 프로젝트에서 코드를 공유하는 매우 큰 코드베이스 (읽기 : 수천 개의 모듈)가 있습니다. 말할 것도없이, 빌드 프로세스를 유지하는 것은 상당히 집안일 수 있습니다.

코드베이스에는 사전 프로세서가 확실하게 무시할 수있는 방법 만 있으면 코드를 실질적으로 정리할 수있는 여러 곳이 있습니다. #includes 파일이 현재 폴더에 존재하지 않은 경우 누구든지 그것을 달성하는 방법을 알고 있습니까?

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

도움이 되었습니까?

해결책

일반적으로 이것은 파일을 포함시키려는 시도에서 전처리기를 실행하는 스크립트를 사용하여 수행됩니다. 사전 처리기가 오류를 반환하는지에 따라 스크립트는 적절한 #define (또는 #undef)로 생성 된 .h 파일을 업데이트합니다. 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

출처

누락 된 헤더를위한 특수 폴더를 만들고 그 폴더를 마지막으로 검색 할 수 있습니다.
(만연한 특유의 - "포함"환경 변수의 마지막 항목, 이와 비슷한 것)

그런 다음 일부 header1.h가 누락 될 수 있다면 해당 폴더에서 스터브를 만듭니다.

header1.h :

#define header1_is_missing

이제 항상 쓸 수 있습니다

#include <header1.h>
#ifdef header1_is_missing

   // there is no header1.h 

#endif

사전 처리기 자체는 파일의 존재를 식별 할 수 없지만 빌드 환경을 사용하여 그렇게 할 수 있습니다. 나는 주로 Make에 익숙합니다. 이것은 당신이 당신의 makefile에서 이와 같은 일을 할 수있게 해줄 것입니다.

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이 언급 한대로 #includ를 조건부로 만들 수 있습니다.

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

또 다른 가능성 : 선택적으로 포함하려는 모든 헤더의 제로 길이 버전이있는 디렉토리를 채우십시오. 이 디렉토리에 -i 인수를 전달하십시오 마지막 그러한 옵션.

GCC CPP는 이전 디렉토리에서 헤더 파일을 찾으면 사용하는 디렉토리를 순서대로 검색합니다. 그렇지 않으면 결국 제로 길이 파일을 찾아 행복 할 것입니다.

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

나는 Symbian OS와 비슷한 일을해야했다. 이것이 내가 한 방식입니다 : "file_strange.h"파일이 존재하는지 확인하고 해당 파일의 존재에 따라 일부 헤더 또는 일부 라이브러리에 링크를 포함시키고 싶다고 가정 해 봅시다.

먼저 해당 파일의 존재를 확인하기 위해 작은 배치 파일을 만듭니다.

Autoconf는 좋지만 많은 소규모 프로젝트에서는 과도하게 살해합니다.

--------- 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 종료

그런 다음 Gnumake 파일을 만들었습니다

------------ 체크 미디어리스트 .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 종료

bld.inf 파일에 Check.mk 파일을 포함 시키려면 MMP 파일 앞에 있어야합니다.

PRJ_MMPFILES
gnumakefile checkmedialist.mk

이제 컴파일 시간에 파일이 있습니다 file_strange_supported.h 적절한 플래그 세트가 있습니다. CPP 파일 또는 MMP 파일 에서이 플래그를 사용할 수 있습니다.

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

그리고 .cpp

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

여기와 인터넷에서 일부 주장과는 달리 Visual Studio 2015는 지원하지 않습니다. __has_include 기능 - 적어도 내 경험에 따라. 업데이트 3으로 테스트.

소문은 2017 년 대 "버전 15"라고도한다는 사실에서 비롯된 것일 수 있습니다. 대신 대신 "버전 14"라고합니다. 이 기능에 대한 지원은 "Visual Studio 2017 버전 15.3"과 함께 공식적으로 소개 된 것으로 보입니다.

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