it-swarm-ko.tech

큰 C ++ 프로젝트에서 불필요한 #include 파일을 어떻게 감지해야합니까?

Visual Studio 2008에서 큰 C++ 프로젝트를 진행 중이며 불필요한 #include 지시어. 때때로 #includes는 단지 아티팩트이며 모든 것이 제거 된 상태에서 정상적으로 컴파일되며, 다른 경우 클래스를 전달할 수 있으며 #include를 .cpp 파일. 이 두 가지 경우를 모두 감지 할 수있는 유용한 도구가 있습니까?

93
shambolic

불필요한 포함 파일을 표시하지는 않지만 Visual Studio에는 포함 된 모든 파일의 트리를 출력하는 /showIncludes 파일 (.cpp 파일을 마우스 오른쪽 단추로 클릭 (Properties->C/C++->Advanced))이 있습니다. 컴파일 타임에. 이것은 포함하지 않아도되는 파일을 식별하는 데 도움이 될 수 있습니다.

또한 pimpl 관용구를 살펴보면 제거 할 수있는 균열을 쉽게 볼 수 있도록 더 적은 헤더 파일 종속성을 피할 수 있습니다.

47
Eclipse

PC Lint 이 기능은 꽤 잘 작동하며 다른 종류의 구피 문제도 모두 찾아냅니다. Visual Studio에서 외부 도구를 만드는 데 사용할 수있는 명령 줄 옵션이 있지만 Visual Lint addin이 더 작업하기 쉽다는 것을 알았습니다. Visual Lint의 무료 버전조차도 도움이됩니다. 그러나 PC-Lint는 기회를 제공합니다. 너무 많은 경고를 제공하지 않도록 구성하는 데 약간의 시간이 걸리지 만 그 결과에 놀랄 것입니다.

29
Joe

이를위한 새로운 Clang 기반 도구 인 include-what-you-use 가 있습니다.

28
Josh Kelley

!!기권!! 상용 정적 분석 도구 (PC Lint가 아님)를 작업하고 있습니다. !!기권!!

간단한 비 파싱 접근 방식에는 몇 가지 문제가 있습니다.

1) 과부하 세트 :

오버로드 된 함수에 다른 파일에서 온 선언이있을 수 있습니다. 하나의 헤더 파일을 제거하면 컴파일 오류가 아닌 다른 과부하가 선택 될 수 있습니다! 결과적으로 의미를 자동으로 변경하여 나중에 추적하기가 매우 어려울 수 있습니다.

2) 템플릿 전문화 :

오버로드 예제와 유사하게, 템플릿에 대한 부분적 또는 명시 적 전문화가있는 경우 템플릿을 사용할 때 모두 표시되도록 할 수 있습니다. 기본 템플릿의 전문화 영역이 다른 헤더 파일에있을 수 있습니다. 특수화로 헤더를 제거해도 컴파일 오류는 발생하지 않지만 해당 특수화를 선택한 경우 정의되지 않은 동작이 발생할 수 있습니다. (참조 : C++ 함수의 템플릿 전문화 가시성 )

'msalters'에 의해 지적 된 바와 같이, 코드의 전체 분석을 수행하면 클래스 사용을 분석 할 수 있습니다. 특정 파일 경로를 통해 클래스가 사용되는 방법을 확인하면 클래스 정의 (및 그에 따른 모든 종속성)를 완전히 제거하거나 적어도 포함의 기본 소스에 가까운 레벨로 이동할 수 있습니다 나무.

26
Richard Corden

나는 그러한 도구를 모르고 과거에 도구를 작성하는 것에 대해 생각했지만 이것이 해결하기 어려운 문제로 판명되었습니다.

소스 파일에 a.h 및 b.h가 포함되어 있다고 가정하십시오. a.h는 #define USE_FEATURE_X와 b.h는 #ifdef USE_FEATURE_X. 만약 #include "a.h"이 (가) 주석 처리되었습니다. 파일이 여전히 컴파일 될 수 있지만 예상 한대로 수행되지 않을 수 있습니다. 이것을 프로그래밍 방식으로 감지하는 것은 쉽지 않습니다.

어떤 도구를 사용하든 빌드 환경도 알아야합니다. a.h가 다음과 같은 경우 :

#if defined( WINNT )
   #define USE_FEATURE_X
#endif

그런 다음 USE_FEATURE_XWINNT이 정의 된 경우에만 정의되므로 도구는 컴파일러 자체에 의해 생성 된 지시문과 헤더 파일이 아닌 컴파일 명령에 지정된 지시문을 알아야합니다.

10
Graeme Perrow

Timmermans와 마찬가지로 저는이를위한 도구에 익숙하지 않습니다. 그러나 Perl (또는 Python) 스크립트를 작성하여 한 번에 하나씩 한 줄씩 주석 처리 한 다음 각 파일을 컴파일하는 프로그래머를 알고 있습니다.


이제 Eric Raymond 이 도구가 있음 인 것으로 보입니다.

Google의 cpplint.py 에는 "사용하는 것 포함"규칙 (다른 많은 것들 중에서도)이 있지만, "include only 사용하고 있습니다. " 그렇더라도 유용 할 수 있습니다.

9
Max Lybbert

이 주제에 대해 전반적으로 관심이 있다면 Lakos의 Large Scale C++ Software Design 을 확인하십시오. 날짜가 조금 있지만 포함해야 할 헤더의 절대 최소값을 찾는 것과 같은 많은 "물리적 디자인"문제가 발생합니다. 나는 다른 곳에서 논의 된 이런 종류의 것을 실제로 보지 못했습니다.

5
Adrian

Include Manager 를 시도하십시오. Visual Studio에 쉽게 통합되고 포함 경로를 시각화하여 불필요한 물건을 찾는 데 도움이됩니다. 내부적으로 Graphviz를 사용하지만 더 멋진 기능이 많이 있습니다. 상용 제품이지만 가격이 매우 낮습니다.

4
Alex

C/C++ Include File Dependencies Watcher 를 사용하여 포함 그래프를 작성하고 불필요한 포함을 시각적으로 찾을 수 있습니다.

4
Vladimir

PC-Lint는 실제로 이것을 할 수 있습니다. 이를 수행하는 쉬운 방법 중 하나는 사용하지 않는 포함 파일 만 감지하고 다른 모든 문제는 무시하도록 구성하는 것입니다. 이것은 메시지 766 ( "모듈에서 사용되지 않는 헤더 파일")을 활성화하기 위해 명령 줄에 -w0 + e766 옵션 만 포함하면됩니다.

964 ( "모듈에서 직접 사용되지 않는 헤더 파일") 및 966 ( "모듈에 사용되지 않은 간접적으로 포함 된 헤더 파일")과 같은 관련 메시지에도 동일한 방법을 사용할 수 있습니다.

FWIW 지난 주 블로그 게시물 http://www.riverblade.co.uk/blog.php?archive=2008_09_01_archive.xml#3575027665614976318 에이 내용에 대해 자세히 썼습니다.

3

헤더 파일이 일반적으로 시작하는 경우

#ifndef __SOMEHEADER_H__
#define __SOMEHEADER_H__
// header contents
#endif

(#pragma를 한 번 사용하는 대신) 다음과 같이 변경할 수 있습니다.

#ifndef __SOMEHEADER_H__
#define __SOMEHEADER_H__
// header contents
#else 
#pragma message("Someheader.h superfluously included")
#endif

그리고 컴파일러는 컴파일되는 cpp 파일의 이름을 출력하므로 적어도 어떤 cpp 파일이 헤더를 여러 번 가져 오는지 알려줍니다.

3
Sam

빌드 시간을 줄이기 위해 불필요한 #include 파일을 제거하려는 경우 cl.exe/MP , make -j , Xoreax IncrediBuild , distcc/ icecream 등.

물론, 병렬 빌드 프로세스가 이미 있고 속도를 높이려고하는 경우 반드시 #include 지시문을 정리하고 불필요한 종속성을 제거하십시오.

2
bk1e

각 포함 파일로 시작하고 각 포함 파일에 자체 컴파일에 필요한 내용 만 포함되어 있는지 확인하십시오. C++ 파일 용으로 누락 된 포함 파일은 C++ 파일 자체에 추가 할 수 있습니다.

각 포함 및 소스 파일에 대해 각 포함 파일을 한 번에 하나씩 주석 처리하고 컴파일되는지 확인하십시오.

포함 파일을 알파벳순으로 정렬하는 것이 좋으며, 이것이 불가능한 경우 주석을 추가하십시오.

2
selwyn

다음 #defines 중 하나 또는 둘 다를 추가하면 불필요한 헤더 파일이 제외되는 경우가 많으며 특히 Windows API 함수를 사용하지 않는 코드의 경우 컴파일 시간이 크게 향상 될 수 있습니다.

#define WIN32_LEAN_AND_MEAN
#define VC_EXTRALEAN

http://support.Microsoft.com/kb/166474 참조

1
Roger Nelson

아직 컴파일하지 않은 경우 미리 컴파일 된 헤더를 사용하여 변경하지 않을 모든 항목 (플랫폼 헤더, 외부 SDK 헤더 또는 이미 완료된 정적 프로젝트)을 포함하면 빌드 시간이 크게 달라집니다.

http://msdn.Microsoft.com/en-us/library/szfdksca (VS.71) .aspx

또한 프로젝트에 너무 늦을 수 있지만 프로젝트를 섹션으로 구성하고 모든 로컬 헤더를 하나의 큰 기본 헤더로 묶지 않는 것이 약간의 추가 작업이 필요하지만 좋은 습관입니다.

1
anon6439

최신 Jetbrains IDE 인 CLion은 현재 파일에 사용되지 않은 포함을 자동으로 표시합니다 (회색으로 표시).

IDE에서 사용되지 않은 모든 포함 (및 함수, 메소드 등)의 목록을 가질 수도 있습니다.

1

Eclipse CDT로 작업하는 경우 http://includator.com 을 사용하여 포함 구조를 최적화 할 수 있습니다. 그러나 Includator는 VC++의 사전 정의 된 포함에 대해 충분히 알지 못하고 올바른 포함으로 VC++를 사용하도록 CDT를 설정하는 것은 아직 CDT에 내장되어 있지 않습니다.

1
PeterSom

어쩌면 조금 늦었지만 한 번은 WebKit Perl 스크립트를 찾았습니다. 내가 생각하는 적응이 필요하지만 (Perl에 정통하지는 않지만) 트릭을 수행해야합니다.

http://trac.webkit.org/browser/branches/old/safari-3-2-branch/WebKitTools/Scripts/find-extra-includes

(이것은 트렁크에 더 이상 파일이 없기 때문에 오래된 지점입니다)

0
rubenvb

더 이상 필요하지 않다고 생각되는 특정 헤더 (예 : string.h)가 있으면 include를 주석 처리 한 다음 모든 include 아래에 넣으십시오.

#ifdef _STRING_H_
#  error string.h is included indirectly
#endif

물론 인터페이스 헤더는 다른 #define 규칙을 사용하여 CPP 메모리에 포함되도록 기록 할 수 있습니다. 또는 컨벤션이 없으면이 방법이 작동하지 않습니다.

그런 다음 다시 빌드하십시오. 세 가지 가능성이 있습니다.

  • 괜찮습니다. string.h는 컴파일에 중요하지 않았으며 포함을 제거 할 수 있습니다.

  • # 오류 트립. string.g가 어떻게 든 간접적으로 포함되었습니다 string.h가 필요한지 여전히 알 수 없습니다. 필요한 경우 직접 #include (아래 참조)해야합니다.

  • 다른 컴파일 오류가 발생합니다. string.h가 필요했고 간접적으로 포함되지 않았으므로 포함이 처음부터 정확했습니다.

.h 또는 .c가 다른 .h를 직접 사용하는 간접 포함에 따라 버그가 거의 확실합니다. 사용중인 다른 헤더가 필요로하는 한 코드에서 해당 헤더 만 필요로한다는 약속이 있습니다. 아마 당신이 의도 한 것이 아닙니다.

동작을 수정하는 헤더에 대한 다른 답변에서 언급 된주의 사항은 빌드 실패를 일으키는 것을 선언하는 것이 여기에도 적용된다는 것입니다.

0
Britton Kerin

기존 답변 중 일부는 어렵다고 말합니다. 전진 선언이 적절한 경우를 감지하려면 전체 컴파일러가 필요하기 때문에 사실입니다. 기호의 의미를 모르면 C++을 구문 분석 할 수 없습니다. 문법이 너무 모호합니다. 특정 이름이 클래스의 이름인지 (앞으로 선언 될 수 있는지) 변수인지 (알 수 없는지) 알아야합니다. 또한 네임 스페이스를 인식해야합니다.

0
MSalters