분할 컴파일
- 프로그래밍/프로그래밍일반
- 2011. 3. 14. 11:11
분할 컴파일 전에 우선 여러분이 작성한 소스파일(.c, .cpp 등 텍스트파일)을 목적파일(.obj 등 2진 파일)로 컴파일하고 여러 목적파일과 라이브러리파일을 묶어 실행파일(.exe)로 만드는 방법을 그림을 통해 알아보도록 하겠습니다.
실행 파일을 만드는 단계는 위와 같이 단계로 나누어집니다.
컴파일러는 사람이 볼 수 있는 소스파일(cpp)을 컴퓨터 프로세스가 인식할 수 있는 목적파일(obj)로 만드는 일을 합니다.
링커는 이렇게 만들어진 컴파일된 파일(목적파일, 라이브러리파일)된 파일을 하나로 묶어 실행파일(exe)로 만드는 일을 합니다.
1, 파일 분할 하기
파일을 분할하는 이유에는 여러가지가 있지만 기본적으로 얻는 이점은 아래와 같습니다.
- 모듈화 프로그램하기 쉽다.
- 코드 수정, 확장이 쉽다.
- 컴파일 시간이 줄어든다.
하여튼 좋답니다. 담에 프로그램 하다 보면 자연스럽게 받아들이게 됩니다. 지금은 패~스!
그럼 분할 컴파일을 하기위해 간단한 예제 하나를 만들어 보도록 하겠습니다.
(두 정수를 교환하고 출력하는 프로그램 입니다.)
// Main.cpp
#include <stdio.h>
void Print( int a, int b)
{
printf("a = %d, b = %d\n", a, b);
}
void Swap( int *a, int *b)
{
int temp = *a;
*a = *b;
*b= temp;
}
void main( )
{
int a = 100;
int b = 500;
Print( a, b);
Swap( &a, &b);
Print( a, b);
}
- a = 100, b = 500
a = 500, b = 100
지금까지 앞쪽 내용을 공부했다면 간단하죠?! ㅡㅡ;;... 아니면 앞 장들을 차근차근 공부하세요~
이제 위 예제 프로그램을 정수 출력 부분과 정수 교환 부분, 함수 호출 부분으로 나누어 컴파일하도록 하겠습니다.
함수를 호출하여 사용하는 측면에서 보면 main()함수측은 클라이언트 코드로 Print()함수와 Swap()함수는 서버 코드로 볼 수 있습니다.
그래서 세부분으로 분할 하도록 하겠습니다.
#include <stdio.h> //printf()를 사용하기 위한 헤더
void Print( int a, int b)
{
printf("a = %d, b = %d\n", a, b);
}
//Swap.cpp 파일
void Swap( int *a, int *b)
{
int temp = *a;
*a = *b;
*b= temp;
}
//Main.cpp 파일
void Print( int , int ); //Print() 함수의 원형
void Swap( int* , int* ); // Swap() 함수의 원형
void main( )
{
int a = 100;
int b = 500;
Print( a, b);
Swap( &a, &b);
Print( a, b);
}
- a = 100, b = 500
a = 500, b = 100
Print.cpp, Swap.cpp, Main.cpp 세 파일로 분할했습니다. 결과는 당연히 위 예제와 같습니다. main.cpp 파일에 보시면 함수의 원형을 선언하고 있습니다. 세 파일이 각각 컴파일 될때 main()함수에서 Print()함수와 Swap()함수를 알 수 없으므로 미리 선언해야 합니다.
아래는 위 예제를 그림으로 표현한 것입니다.
만약, 위 예제의 Print()함수를 작성한 사람과 Swap()함수를 작성한 사람과 main() 코드를 작성하는 사람이 모두 다르다면 위 예제의 어떤 부분이 잘못되었을까요?
............. 음.....
== > Main.cpp를 잘 보시면 함수의 원형을 선언(Print.cpp, Swap.cpp)하고 있습니다. 하지만 Main.cpp를 작성하는 사람과 Print,Swap 코드를 제공하는 사람이 다르므로 Main.cpp에서 함수의 원형(Print,Swap)을 선언하는 것은 쉬운 일이 아닙니다. 함수가 많다거나 함수가 복잡하다거나 만약 소스파일이 존재하지 않는다면??
==> 그럼 위 문제를 어떻게 해결할까요? 당근당근!
Print()함수의 원형은 Print.cpp를 만드는 사람이 제공해야합니다. Swap()함수의 원형은 Swap()함수를 만드는 사람이 제공해야합니다. 그래서 헤더파일이 필요합니다.
보통 서비스코드(서버코드, 여기서는 Print(), Swap() )를 만드는 사람은 세 가지를 제공해야 합니다.
- 첫째, 헤더파일 (Print.h, Swap.h)
- 둘째, 소스파일이나 라이브러리파일(Print.cpp, Swap.cpp나 lib, dll 등)
- 셋째, 그리고 부가적인 함수 사용 도움말!
아래 예제는 헤더파일(Print.h, Swap,h)을 사용한 예제 코드입니다.
#ifndef __PRINT_H_AAAHHHEEE
#define __PRINT_H_AAAHHHEEE
void Print( int , int ) ;
#endif
#include <stdio.h> //printf()를 사용하기 위한 헤더
void Print( int a, int b)
{
printf("a = %d, b = %d\n", a, b);
}
#ifndef __SWAP_H_KKEEKKKKKK
#define __SWAP_H_KKEEKKKKKK
void Swap( int *, int *);
#endif
//Swap.cpp 파일
void Swap( int *a, int *b)
{
int temp = *a;
*a = *b;
*b= temp;
}
//Main.cpp 파일
#include "Print.h" //Print.cpp에서 제공#include "Swap.h" //Swap.cpp에서 제공
void main( )
{
int a = 100;
int b = 500;
Print( a, b);
Swap( &a, &b);
Print( a, b);
}
- a = 100, b = 500
a = 500, b = 100
결과는 같습니다. 헤더파일(Print.h, Swap.h)의 전처리 #ifndef는 헤더파일을 중복으로 포함하지 않기 위함입니다. 전처리 장을 참고하시고 어려우면 지금은 그냥 저렇게 쓰면 된다고 알아 두세요.
서버 코드가 제공해야 하는 3가지는 아래 그림을 참고하세요.
출저: http://blog.daum.net/coolprogramming/40
항상 코딩을 하다보면 링크에러가 많이 나는데 이것은 보통 분할 컴파일땜에 그렇다.
보통 많이 실수 하는 것은 헤더파일을 2번이상 참조했을 경우이다.
헤더가 꼬였을때 해결책은
#include 같은 전처리기에 대해서 생각해보면 알수있다.
이 글을 공유하기