신입 게임 개발자의 프로그래밍 일기
[C++ 입문자에서 벗어나기]Chapter_3: 빌드(Build)#1 본문
[C++ 입문자에서 벗어나기]Chapter_3: 빌드(Build)#1
이번 포스팅부터는 빌드에 대해 이야기해보겠습니다.
빌드는 IDE에 익숙한 몇몇 저와 같은 초심자들에게는 그냥 지나가는 단계였습니다.
(그냥 VisualSutdio에서 빌드 버튼 누르면 알아서 모든 단계가 진행되기 때문이죠...)
그냥 지나치던 빌드라는 과정에 대해서 좀 파해쳐보려고 합니다.
[빌드(Build)란?]
이전 포스팅에서 다뤘던 것처럼 빌드는 최종적으로 실행바이너리를 생성하기 위한 일련의 과정입니다.
이 과정은 3단계로 나뉘는데 그것들은 전처리, 컴파일, 링크 단계입니다.
곧바로 전처리 단계에 대해 이야기 해보겠습니다.
[전처리 단계]
전처리문이라는 용어에 들어본 적이 있으실 겁니다.
없으시다면 #include 이 지시문은 어떠신가요?
이 키워드는 모르실래야 모르실 수 가 없으실 겁니다.
#include는 보통 선언 코드들이 포함된 헤더파일을 포함시키기 위해 사용하는 전처리 지시문입니다.
" ", < > 이 두 가지 문법으로 #include를 사용하실겁니다.
그리고 우리는 이 둘의 차이를 전자는 사용자가 직접 제작한 파일을 위해서 후자는 기존 CRT Library 및 시스템에서 제공하는 파일을 포함시키고자 할 때 사용함을 알고 계실겁니다.
이 두가지 include문이 어느 디렉터리들을 검색하는 지를 확인해봅시다.
" " | 접근 및 검색 디렉터리 | < > |
(1) | #include문이 포함된 파일과 동일한 디렉터리 검색 | X |
(2) | /I 컴파일러 옵션(보통 IDE의 포함 디렉터리)에 지정된 경로를 따라서 검색 | (1) |
(3) | INCLUDE 환경 변수에 지정한 경로를 따라서 검색 | (2) |
위 표에서 확인 할 수 있듯히 " "범위 검색이 한 단계 더 포괄적임을 알 수 있습니다.
#include <iostream> #include "iostream" 둘다 맞는 문법입니다.
추가적으로 헤더파일(.h) 작성 시, 전역 변수나 전역 함수의 정의를 포함시키지 않고 선언 코드만을 작성하시기 바랍니다. (전역 변수에는 extern 키워드, 전역 함수의 몸체 작성하지 말 것!)
그 이유는 헤더파일을 중복 #include 할 경우, 링크 단계에서 정복 정의 에러가 발생함으로 이 점 유의하시기 바랍니다.
두번째로 살펴볼 전처리문은 #define입니다.
이 전처리문은 아래와 같은 문법으로 사용이 가능합니다.
#define identifier token-string
#define identifier
첫번째 문법은 코드에서 identifier를 token-string으로 대체하라는 매크로입니다.
두번째 문법은 identifier를 정의하라는 매크로입니다. 이 identifier가 코드에 존재할 시에는 컴파일 에러가 발생하게 됩니다.
#define으로 함수 매크로를 만들 수 있지만 이보다는 인라인 함수를 사용하는 것이 대체적으로 좋습니다. 물론 함수 매크로가 필요한 경우가 있습니다.(ex. 로그)
세번째로 살펴볼 전처리문은 #undef입니다.
#define으로 정의한 매크로를 해제하는 전처리문입니다.
그다음으로는 조건부 컴파일 지시문들입니다.
#if, #ifdef, #ifndef, #else, #elif, #endif와 같은 것들입니다.
if문과 사용 방법이 비슷합니다.
마지막으로 소개해드릴 매크로는 #pragma once 입니다.
이 매크로의 기능은 아래와 같습니다.
컴파일러가 cpp파일 하나를 컴파일 하고 있습니다. 그런데 이 cpp파일에 #include "A.h"라는 지시문이 두 개 이상일 경우, 첫번째 #include "A.h" 지시문만 수행하고 그다음부터는 #include "A.h" 수행하지 말라고 컴파일에게 알려줍니다.
#paragma once 매크로는 표준이 아니지만 VC++과 gcc에서 모두 지원됩니다.
#pragma once의 기능은 include guard라는 조건 컴파일 지시문을 활용한 기법으로 유사하게 동작시킬 수 있습니다.
아래에 소개시켜드리는 매크로들은 로그 혹은 호환성있는 프로그램 작성에 도움을 줄 수 있는 매크로 몇가지입니다.
자세한 사항은 아래 MSDN을 참고하세요.
(MSDN 미리 정의된 매크로: https://msdn.microsoft.com/ko-kr/library/b0084kay(v=vs.120).aspx)
[로그를 남길때 사용하는 매크로들]
_FILE_과 _LINE_은 각각 "현재 소스 파일 이름"과 "현재 소스 파일의 줄 번호"를 나타냅니다.
이것들은 주로 로그를 남길 대 사용되는데 디버깅을 하거나 실행 분석을 할 경우에 유용합니다.
[Microsoft 전용 미리 정의된 매크로들]
최근의 CPU들은 x86과 x64를 동시 지원하기 때문에 시스템별로 별도의 개발이 필요한 경우가 많아지고 있습니다.
동일한 코드를 시스템 별로 따로 작성하는 것은 손해임으로 시스템 별로 별도의 작업이 필요한 코드들만을 매크로로 구분시켜서 컴파일 하는 것이 효율적입니다.
아래 표는 fundamental C++ 프로그래밍 원리 Chapter 3 빌드에서 제공하는 표입니다.
| Win32(x86) | x64 | IA64 |
_WIN32 | V | V | V |
WIN32 | V | V | V |
_WIN64 | | V | V |
_M_IX86 | V | | |
_M_X64 | | V | |
_M_AMD64 | | V | |
_M_IA64 | | | V |
[미리 컴파일된 헤더(Pre-Compiled Header)]
windows 프로그래밍을 하다보면 stdafx.h라는 헤더파일이 자동으로 생성되는 것을 보신 적이 있을 겁니다.
이 헤더파일은 default로 설정된 Pre-Compiled header입니다. VC++의 경우 .pch 확장자로 GCC에서는 .gch 확장자로 관리합니다. 이 기능은 재컴파일될 필요성이 없는 헤더파일들을 모아서 컴파일을 한번만 하고 그 이후부터 컴파일을 하지 않고 이용하는 것이 핵심입니다. STL과 같이 코드가 변경되지 않아서 재컴파일이 필요없는 라이브러리들은 한곳에 모아서 미리 컴파일된 헤더로 설정하면 컴파일 시간이 많이 단축될 수 있습니다.
'Language > C++' 카테고리의 다른 글
ISO Cpp 게시글 Memory Management와 관련된 여러 질문들 (0) | 2017.12.11 |
---|---|
[C++ 입문자에서 벗어나기]Chapter_3: 빌드(Build)#2 (0) | 2017.12.01 |
[C++ 입문자에서 벗어나기]Chapter_2: 선언과 정의#3 (0) | 2017.11.09 |
[C++ 입문자에서 벗어나기]Chapter_2: 선언과 정의#2 (0) | 2017.11.08 |
[C++ 입문자에서 벗어나기]Chapter_2: 선언과 정의#1 (0) | 2017.11.05 |