본문 바로가기
공부/TIL

[TIL]2022/03/22 C 다중소스 분할 컴파일

by 노르웨이모리 2022. 3. 22.

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