사용자 도구

사이트 도구


kb:visualcppbuildtimespeedup

Visual C++ Build Time Speedup

Visual C++의 빌드 속도를 빠르게 하는 방법들이다.

Precompiled Header

빌드 속도를 빠르게 하기 위해서 가장 우선적으로 해야할 일이다.

미리 컴파일된 헤더의 기능을 쉽게(?) 설명하자면… 모든 소스(.cpp) 파일에 포함될 헤더 파일(.h)을 하나 정해, 미리 컴파일해서 캐시로 만들어 두고, 각각의 cpp 파일을 컴파일할 때 그 캐시를 활용하자는 것이다.

어디까지나 캐시이므로, 자주 변하면 의미가 없다. 그러므로 잘 변하지 않는, 대표적으로 <windows.h> 같은 파일이 대상이 된다고 할 수 있다. 프로젝트 내부에서도 잘 변하지 않는 타입 헤더 같은 것들이 있다면 포함시켜도 좋다. 대표적으로 [STL] 헤더 파일들을 포함하는 경우를 들 수 있겠다.

미리 컴파일된 헤더를 사용하는 과정을 순서대로 도식화하자면 다음과 같다.

1. 미리 컴파일된 헤더로 사용할 헤더 파일과 소스 파일을 하나 만든다. 이 파일을 pch.h, pch.cpp 라고 하자.

2. pch.h 파일 내부에 대충 다음과 같은 내용들을 집어넣는다.

#pragma once
 
#include <windows.h>
#include <string>
#include <list>
...

3. pch.cpp 파일 내부에 다음과 같은 내용을 집어넣는다.

#include "pch.h"

4. 모든 소스 파일의 제일 윗쪽 라인에다

#include "pch.h"

구문을 집어넣는다. 여기서 제일 윗쪽 라인이라는 것은 다른 include 구문이나, 소스가

#include "pch.h"

구문보다 먼저 나오면 안 된다는 말이다.

5. 프로젝트 속성 –> C/C++ –> 미리 컴파일된 헤더로 가서, 미리 컴파일된 헤더 만들기/사용 항목을 미리 컴파일된 헤더 사용 (/Yu)로 바꾸어준다. 그리고 파일로 PCH 만들기/사용 항목에다 pch.h라고 적어준다.

6. pch.cpp 를 선택해서 속성 창을 연다. C/C++ –> 미리 컴파일된 헤더로 가서, 미리 컴파일된 헤더 만들기/사용 항목을 미리 컴파일된 헤더 만들기 (/Yc)로 바꾸어준다.

7. 리빌드한다.

컴파일 및 링크 옵션

  • 최소 다시 빌드 : 프로젝트 속성 –> C/C++ –> 코드 생성 –> 최소 다시 빌드 가능 –> 예(/Gm)
  • 증분 링크 : 프로젝트 속성 –> 링커 –> 증분 링크 사용 –> 예(/INCREMENTAL)
  • 동적 C 런타임 사용 : 프로젝트 속성 –> C/C++ –> 코드 생성 –> 런타임 라이브러리 –> 다중 스레드 DLL(/MD) 또는 다중 스레드 디버그 DLL(/MDd)

VC_EXTRALEAN 및 WIN32_LEAN_AND_MEAN

MFC 위자드가 생성해 주는 프로젝트를 보면, stdafx.h 파일에 VC_EXTRALEAN 및 WIN32_LEAN_AND_MEAN를 정의해주는 것을 볼 수 있다. 이 값이 하는 역할은 afxv_w32.h 파일을 보면 알 수 있는데 다음과 같다.

...생략...
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
 
...생략...
 
#ifdef VC_EXTRALEAN
#define NOSERVICE
#define NOMCX
#define NOIME
#define NOSOUND
#define NOCOMM
#define NORPC
 
...생략...
 
#endif //VC_EXTRALEAN
 
...생략...
 
#include <windows.h>
...생략...

NOxxx 시리즈를 정의해주는 것을 볼 수 있다. 즉 MFC를 사용하지 않는 애플리케이션에서도, 이 값들을 windows.h 파일을 포함하기 전에 정의해 주면, 해당 서비스와 관련된 헤더들이 빠지게 된다는 말이다. windows.h 파일에 보면 다음과 같은 NOxxx 시리즈가 있는 걸 볼 수 있다.

/*  If defined, the following flags inhibit definition
  *     of the indicated items.
  *
  *  NOGDICAPMASKS     - CC_*, LC_*, PC_*, CP_*, TC_*, RC_
  *  NOVIRTUALKEYCODES - VK_*
  *  NOWINMESSAGES     - WM_*, EM_*, LB_*, CB_*

 ...생략...

  *  NOPROFILER        - Profiler interface.
  *  NODEFERWINDOWPOS  - DeferWindowPos routines
  *  NOMCX             - Modem Configuration Extensions
  */

헤더 가드

모든 헤더 파일에 #ifndef #define 구문 또는 #pragma once 구문을 사용한다. 기본적인 내용이고, Visual C++에만 국한되는 내용도 아니다.

헤더 파일을 정의할 때 뿐만 아니라, 포함할 때도, 추가적으로 가드를 써주면 좋다. 다음과 같은 헤더 파일이 있다고 하자.

#ifndef __SOMEHEADER_H__
#define __SOMEHEADER_H__
...생략...
#endif // end of __SOMEHEADER_H__

이 파일을 다른 헤더에서 포함할 때 다음과 같은 방식으로 하는 것이다.

#ifndef __SOMEHEADER_H__
#include "SomeHeader.h"
#endif

왜 이런 식으로 하는 게 의미가 있느냐 하면, 추가적인 가드가 없을 때에는 컴파일러가 일단 헤더 파일을 열어서 확인을 하게 된다. 그 헤더 파일 안의 내용을 이전에 포함시킨 적이 있건 없건 말이다. 그런데 가드가 있으면 두번째부터는 아예 파일 열기를 시도하지 않게 된다. 그래서 약간이나마 빨라진다는 말이다. (사실 속도의 증가는 체감한 적이 없다.)

이에 관한 사항은 “Large-Scale C++ Software Design”이라는 책에 잘 나와있다.

종속성 검사시 체크하지 않을 파일 목록 지정하기

소스 파일에서 어떤 헤더 파일을 포함(include)하게 되면, 그 소스 파일은 그 헤더 파일에 종속된다. 이런 경우 알다시피 헤더가 변경되면, 소스 또한 컴파일해야 한다.

디버그 메뉴 등을 통해 프로그램을 실행하는 경우, Visual C++은 변경된 헤더 파일을 자동으로 감지해서, 새로 컴파일해야할 소스 파일을 찾아낸다. 여기서 생각할 수 있는 건, 변경되지 않는 헤더 파일(대표적으로 외부 라이브러리의 헤더 파일)이 있으면, 그 파일에 대한 종속성 검사는 생략해도 된다는 것이다.

...\Local Settings\Application Data\Microsoft\VisualStudio\7.1

위 디렉토리(2003의 경우, 2002는 아마도 7.0이겠지) 안에 보면,

SysIncl.dat

파일이 있다. 이 파일을 텍스트 편집기로 열어서, 한 줄에 하나씩 완전한 디렉터리 이름(완전한 절대 경로)을 추가하면, 그 디렉토리 하위에 있는 헤더 파일들에 대해서는 종속성 체크를 생략하게 된다. (IDE를 재시작한 후, 다시 빌드를 한번 해야한다.)

당연하지만, “다시 빌드”를 수행하는 경우, 종속성 체크가 필요없으므로, “다시 빌드”가 빨라지는 것은 아니다.

:!: 기본적으로 Visual C++은 VC7 디렉토리 및 그 하위 디렉토리에 있는 모든 파일에 대해서는 종속성 검사를 하지 않는다.

링크

  • How Can I Build Faster?
    빌드 시간 단축 방법에 대한 소개. Visual Studio 2003에 딸려오는 한글판 MSDN의 경우, “빌드 시간 단축 방법”으로 검색하면 같은 내용이 나온다.
  • IncrediBuild
    랜 상에 있는 여러 컴퓨터를 활용해 빌드 속도를 올려주는 솔루션.

kb/visualcppbuildtimespeedup.txt · 마지막으로 수정됨: 2014/11/09 21:23 (바깥 편집)