C 다중소스 분할 컴파일
C로 큰 프로젝트를 만들 때는 한 .c 파일에 모든 코드를 작성하지 않는다.
main 함수가 들어있는 main.c 랑 나머지 함수들이 들어가는 함수1.c, 함수2.c, 헤더.h 등등으로 여러 개의 c 파일을 생성해서 컴파일 할 때 합친다.
컴파일할 때 합친다는 건 알겠는데 각 파일마다 들어있는 내용을 어떻게 작성해야 하는 건지에는 생각해보지 않았다.
예를 들어서 다음과 같은 프로그램이 있다고 하자. 다중소스를 사용하지 않고 하나의 c 파일에서 프로그램을 작성한다면 다음과 같다.
#include <stdio.h>
void director();
void film();
int main(){
printf("Executing main()\n");
film();
director();
return 0;
}
void director(){
printf("Executing director()\n");
}
void film(){
printf("Executing film()\n");
}
이 프로그램을 다중소스로 나눠서 작성하려면 어떻게 해야 할까?
우선은 main.c, director.c, film.c 세 개의 파일에 각각의 함수를 집어 넣으려고 한다.
그리고 movie.h 헤더를 작성해 프로그램이 사용하는 헤더들, 매크로, 사용자 정의 상수 들을 불러오려고 한다. 물론 이 예시에서는 매크로랑 사용자 정의 상수는 없지만.
이렇게 생각하면 엄청 간단한 거 같다. 하나의 파일에 작성된 코드를 나눠보기만 하면 다음과 같을 것이다.
//main.c
int main(){
printf("Executing main()\n");
film();
director();
return 0;
}
//director.c
void director(){
printf("Executing director()\n");
}
//film.c
void film(){
printf("Executing film()\n");
}
//movie.h
#include <stdio.h>
근데 이런 파일들을 만들어서 컴파일하면 제대로 컴파일이 안된다.
왜냐하면 지금 위 파일들은 처음의 큰 프로그램을 작은 부분으로 나눠서 각자의 파일에 저장된 건데, 이렇게 각자의 파일에 코드가 저장되니 서로의 연관성, 관련성을 상실해버린 것이다.
예를 들어서 프로그램이 시작되어 main함수가 film() 함수를 실행시킬 때 main.c에서는 film() 함수에 대한 정의가 없기 때문에 컴파일러가 알아듣지 못한다.
우리는 그냥 파일을 각 함수마다 나눠서 만들어 컴파일을 한꺼번에 해주면 알아서 서로 연결되어 이해할 거라고 생각하지만, 실제로는 그렇지 않고 우리가 만든 다중소스에서 각 소스끼리의 언급을 통해 연관성을 직접 알려줘야 한다.
마찬가지로 main함수가 실행되고 printf를 해야하는데 main.c에는 stdio이 정의되지 않아서 프린트도 할 수 없다.
파일을 만들 때 movie.h에 stdio를 넣어주고 movie.h를 같이 컴파일 했다고 각 c 파일들이 이 헤더를 이해할 수 있는 게 아니다. 마찬가지로 각 c 소스 파일들에 movie.h를 include 한다는 말을 해줘야 한다.
그렇기 때문에 올바르게 작성한 다중소스 코드들은 다음과 같다.
//main.c
#include "movie.h"
int main(){
printf("Executing main()\n");
film();
director();
return 0;
}
//film.c
#include "movie.h"
void film(){
printf("Executing film()\n");
}
//director.c
#include "movie.h"
void director(){
printf("Executing director()\n");
}
//movie.h
#include <stdio.h>
void director();
void film();
이 코드들에는 각 c 소스 파일마다 movie.h를 불러오고 있다. movie.h에는 stdio과 director(), film() 함수에 대한 정의가 들어있기 때문에 movie.h를 불러오는 것은 stdio, director(), film()의 정의를 불러오는 것과 같다.
이게 각 c 소스 파일들은 stdio와 함수에 대한 정의가 있으므로 제대로된 함수 호출을 할 수 있다.
결론적으로,
각 .c 파일 위에는 그 파일이 사용할 헤더를 include 해야함. 불어올 헤더 파일은 사용자가 직접 생성해 (movie.h 처럼) 불어올 것들을 한꺼번에 불러올 수 있음. 헤더 파일에 함수 정의들도 적어서 부를 수 있음.
함수 정의들(director(), film() 함수들)을 헤더 파일에 안적고 main.c 파일에만 적어도 컴파일이 될까 궁금했다.
main.c 파일에 이 함수들이 실행되는 코드가 있기 때문에 main.c에서만 호출하니 여기에만 써도 될 거 같았다.
그런데 아니다.
//main.c
#include <stdio.h>
void director();
void film();
int main(){
printf("Executing main()\n");
film();
director();
return 0;
}
film()함수를 여전히 모르는 거 같았다. 그래서 이번에는 main.c, director.c, film.c 모두에게 맨 위에 함수 정의를 해주었다.
//main.c
#include <stdio.h>
void director();
void film();
int main(){
printf("Executing main()\n");
film();
director();
return 0;
}
//director.c
#include <stdio.h>
void director();
void director(){
printf("Executing director()\n");
}
//film.c
#include <stdio.h>
void film();
void film(){
printf("Executing film()\n");
}
main.c 에는 director(), film() 두 함수 모두가 쓰이니 둘 다 정의했고, film.c 과 director.c에는 자기 함수만 정의했다.
이렇게 컴파일을 해보니 잘 되었다.
결국에는 main.c 에서 director(), film()함수가 실행된다고 해서 main.c에만 두 함수를 정의해서는 안되고, director.c, film.c 자체에서도 자기 함수를 정의해줘야한다.
이렇게 실험을 해 보니 그냥 movie.h 처럼 하나의 헤더 파일을 정의해서 여기다가 함수들 정의를 다 집어 넣고 각 .c 파일에는 헤더 파일만 불러오는 게 더 효율적인 거 같다.
추가로,
윈도우에서 git bash를 사용해 Makefile을 생성해 다중소스 컴파일을 하려고 하면 make 커맨드를 실행하지 못하는 오류가 발생한다.
윈도우에는 make 명령어 대신에 mingw32-make 명령어를 사용해야 한다.
'공부 > TIL' 카테고리의 다른 글
[TIL]2022/03/09 (0) | 2022.03.09 |
---|---|
[TIL]2022/03/08 (0) | 2022.03.08 |
[TIL]2022/03/05 (0) | 2022.03.05 |
[TIL]2022/03/01 (0) | 2022.03.01 |
[TIL]2022/02/22 (0) | 2022.02.22 |