코딩을 하다 보면 프로젝트의 몸집이 커지게 되고, 그에 비례하여 컴파일 타임도 기하급수적으로 늘어나게 됩니다. 단지 코드 몇줄 수정하고 추가 했을 뿐인데 매번 컴파일 타임이 수분~수십분 걸리게 되면 작업의 리듬도 깨지게 되고 프로그래머의 능률은 저하되게 되죠. 그래서 빌드 타임을 최소화 하기 위한 여러 기법들이 있습니다. 인크레디 빌드 IncrediBuild 같은 서드 파티의 도움을 받을 수도 있고, 오늘 소개 해드릴 미리 컴파일 된 헤더를 사용하는 방법등이 있습니다.
미리 컴파일 된 헤더(Precompiled Header)는 무엇인가요?
단어 그대로 헤더 파일들을 미리 컴파일 해두는 것입니다. 미리 컴파일 된 헤더를 만들면 pch 라는 파일이 생성 되는데 컴파일러는 이를 참조하여 프로젝트 컴파일을 수행하게 됩니다. 미리 컴파일 시킨 헤더를 참조하니 기존에 헤더 파일을 일일히 파싱하던 때에 비해서 컴파일 속도가 빠른 것 입니다.
이미지 출처 : MSDN
미리 컴파일된 헤더를 사용하는 방법은 간단합니다. 일단 미리 컴파일 된 헤더로 사용될 헤더 파일(.h)과 소스 파일(.cpp)을 프로젝트에 추가 합니다. ( 이하 Visual Studio 기준 )
그 다음 프로젝트 속성에 들어가 미리 컴파일 된 헤더를 사용하겠다는 설정 해줍니다.
추가한 cpp 파일의 속성 메뉴에 들어가 미리 컴파일 된 헤더 만들기를 설정 해줍니다. 이를 통해 Precompiled.h 파일에서 참조 하고 있는 헤더 파일들을 미리 컴파일 하게 됩니다.
이로서 미리 컴파일 된 헤더 사용 하기의 준비는 모두 끝났습니다.
어떤 헤더 파일을 미리 컴파일 시켜야 할까?
앞서 미리 컴파일된 헤더를 쓰면 빌드 타임이 줄어든다고 했습니다. 그렇다면 많은 헤더들을 추가 하면 좋을까요? 결론은 아닙니다. 미리 컴파일 된 헤더에 포함 시킬 헤더를 선정하는 것은 신중 해야 합니다. 예로 미리 컴파일 된 헤더에 포함된 파일이 수정이 일어나면 미리 컴파일 된 헤더도 새로 만들게 됩니다. 이렇게 되면 미리 컴파일 된 헤더를 사용하는 의미가 없어집니다. MSDN을 보면 다음 사항에 미리 컴파일된 헤더 파일 사용을 권장하고 있습니다.
- 자주 바뀌지 않고 크기가 큰 코드 본문을 항상 사용합니다.
- 프로그램이 여러 개의 모듈로 구성되어 있으며, 모든 모듈이 포함 파일의 표준 집합 및 동일한 컴파일 옵션을 사용합니다. 이 경우 모든 포함 파일을 미리 컴파일해서 하나의 미리 컴파일된 헤더로 만들 수 있습니다.
여기서 핵심은 자주 바뀌지 않고라 할수 있습니다. 대표적으로 STL 헤더 같은 것을 생각할 수 있습니다. 이들의 헤더 파일은 거의 바뀔일이 없죠. 그 외에 프로젝트에 사용하는 서드파티 라이브러리 헤더 파일이라든가 한번 만들어두고 수정할일 없는 헤더 파일이 있는 경우 추가해주면 좋습니다. 실제로 사용 예제 코드를 살펴 보겠습니다.
// Precompiled.h #pragma once #include <string> #include <vector> #include <list>
// Precompiled.cpp와 미리 컴파일된 헤더를 사용하는 프로젝트의 모든 cpp 파일에 추가 #include "Precompiled.h"
위와 같이 헤더 파일을 추가 해 되면 string, vector, list 헤더 파일은 미리 컴파일 되게 됩니다. 이로 인해 생기는 이점이 하나 더 있습니다. vector와 list를 사용할때 일일히 #inlcude <vector> 를 추가할 필요가 없어지는 겁니다. 간단히 이야기 해 #include <vector> 구문이 전역적으로 적용되는 것과 같은 효과가 발생하게 됩니다.
자그마한 관심으로 컴파일 시간이 줄어들수 있습니다
미리 컴파일된 헤더를 사용하는 것 외에도 작은 습관 하나로 컴파일 타임을 줄이는 법도 있습니다. 다음과 같이 헤더 파일이 있다고 가정해보겠습니다.
// Foo.h #include "Bar.h" class Foo { private: Bar mBar; };
Foo라는 클래스에서 Bar 클래스를 멤버 변수로 가지고 있습니다. 이를 위해 Bar 클래스가 선언 되어있는 헤더 파일을 포함하고 있습니다. 그런데 어느 순간 Bar 클래스가 수정되었다고 가정해보겠습니다. 그러면 컴파일 시에 Bar 헤더를 포함해 Foo 헤더까지 재 컴파일을 하게 됩니다. 어찌 보면 당연한 결과지만 작은 수정을 통해 이를 방지할 수 있는 방법이 있습니다.
// Foo.h class Bar; class Foo { private: Bar *mpBar; }; // Foo.cpp #include "Bar.h"
바뀐 부분을 보시면 Bar 멤버변수가 포인터로 변했고, include 를 안하는 대신 전방 선언을 넣었습니다. 그리고 Bar 클래스를 사용하는 본문 파일에 include를 추가하였습니다. 이렇게 변환 하였을 경우 Bar 클래스의 수정이 일어나도 Foo.h 파일은 재 컴파일이 일어나지 않게됩니다. 컴파일 타임이 줄어 드는 것이죠.
참조
미리 컴파일된 헤더를 사용하자
MSDN 미리 컴파일된 헤더 파일 만들기
빌드 시간에 관한 고찰
'프로그래밍' 카테고리의 다른 글
CUDA를 이용한 실시간 Ambient Occlusion (4) | 2012.04.06 |
---|---|
Wrapped Diffuse (4) | 2012.04.03 |
유니티3D엔진을 배워 봅시다. 1강. 디버깅 객체 살펴보기 (15) | 2012.03.17 |
컴파일 경고하나당 3대씩 맞습니다 (28) | 2012.03.16 |
게임 오브젝트 설계.. 나도 잘하고 싶다! #3 (21) | 2012.03.15 |