본문 바로가기

IT/Linux

CMake Build System / gcc, make, cmake 차이점

리눅스에서는 보통 편집기와 컴파일러가 분리되어있다. 리눅스에서의 통합개발환경이란 VS처럼 자체적인 컴파일러까지 포함하는게 아니고 리눅스에 기본 설치된 컴파일러인 gcc를 잘 가져다 쓰는 코드 편집기를 말한다. IDE 마다 각자의 방식으로 소스코드 목록과 의존성을 관리하는 프로젝트 파일을 만드는데 소프트웨어를 배포할 때 특정 IDE의 프로젝트 파일을 배포하게 되면 그 소프트웨어를 받아서 쓰는 사람도 특정 IDE를 설치해야 하는 번거로움이 있다. 그래서 리눅스에서 공통적으로 사용하는 빌드 시스템이 있는데 바로 make cmake다. 그래서 소프트웨어을 개발할 때는 편리한 IDE를 쓰고 배포하거나 남의 소프트웨어를 가져다 쓸 때는 command line에서 리눅스 빌드툴을 써서 직접 빌드를 한다. gcc, make, cmake의 관계는 다음과 같다.

 

 

  • gcc: GNU Compiler Collection의 약자로 C/C++의 컴파일러이다.
  • make: 여러 단계의 gcc 명령을 Makefile 이라는 스크립트로 만들어 한번에 실행하게 하고 Incremental Build를 지원한다.
  • cmake: 중간 단계를 일일이 지정해줘야 하는 복잡한 Makefile을 좀 더 편리하게 만들어준다. 이를 위해 CMakeLists.txt라는 스크립트를 작성해야 한다.

 

gcc를 직접 쓰기 불편해서 make가 생겼는데 프로젝트가 복잡해지면 Makefile 작성하기도 어려워서 cmake가 생겼단다. 

 

 

1.1 gcc and make

예를 들어 다음과 같은 구조를 가진 소스 코드를 빌드하고자 한다.

소스 코드는 다음과 같다.

이를 빌드하려면 다음 명령어를 실행한다. C언어를 빌드할 때는 gcc를 쓰고 C++을 빌드할 때는 g++을 쓴다. 아래 명령어는 각각의 *.c 파일을 컴파일하여 object 파일(*.o)을 만들고 이들을 묶어 실행 파일 myapp을 빌드한다.

겨우 몇 개의 파일을 결합하여 빌드하는데 네 번의 명령어를 입력해야 하고 더 싫은건 코드를 수정할 때마다 같은 과정을 반복해야 한다는 것이다. 물론 foo만 수정하는경우 두 번째와 네 번째 명령어만 쓰면 되지만 어쨌든 매우 번거로운 과정이다. 이 과정을 쉘 스크립트로 작성하는 방법도 있지만 그러면 수정할 때마다 전체 빌드를 다시 하게 되므로 수정사항을 확인하는데 시간이 오래 걸릴 것이다.

 

 

그래서 나온 것이 make다. 방금 말한대로 빌드과정을 make의 문법에 맞춰 스크립트로 작성한 후 make 명령어를 통해 한 번에 빌드할 수 있다. 위의 g++ 명령어를 그대로 쓴 것과의 차이점은 Incremental Build가 가능하다는 것이다. 즉 변경한 부분만 알아서 빌드를 해준다. 다음과 같이 Makefile을 작성하고 make 명령어를 실행해보자.

 

자세한 Makefile 문법은 나도 잘 모르니까 넘어가기로 하고 파일들의 의존 관계를 기술했다는 것만 이해하고 넘어가자. 어쨌든 이렇게 Makefile을 만들고 make라는 실행하면 빌드가 되는데 중요한 것은 알아서 변경한 부분만 빌드해준다는 것이다. make를 실행한 후 한번 더 make를 실행해보거나 소스 파일 하나만 수정한 후 make를 실행해서 나오는 출력을 보면 이해할 수 있다.

그러나 이것도 프로젝트 규모가 커지면 Makefile을 관리하는 것도 점점 버거워진다. 일단 소스 파일이 많아지면 중간 결과물 (*.o)도 많아지고 파일들의 의존 관계를 코드가 바뀔때마다 수정해주는 것도 번거롭고 빌드 target이 여러 개이거나 프로젝트가 다단계(?)로 이루어진 경우 등 Makefile은 쉽게 방대해지고 관리하기가 어려워진다.

그래서 우리에게 필요한 것은? CMake


1.2 CMake

이번엔 cmake로 같은 프로젝트를 빌드해보자. 위 예제에서 cmake를 위한 설정 파일인 CMakeLists.txt를 한 줄만 쓰면 빌드가 된다. make와 cmake의 가장 큰 차이는 중간 단계를 생략해도 된다는 것이다. make는 중간 단계에서 생기는 object 파일들을 일일이 지정하고 소스 사이의 의존 관계도 직접 지정해줘야 하지만 cmake는 중간단계는 알아서 만들어주고 소스코드를 분석하여 의존성도 알아서 찾는다. 그래서 소스 파일과 결과물만 지정하면 된다. ADD_EXCUTABLE() 함수는 타겟과 그것을 빌드하는데 필요한 소스 파일을 지정한다. cmake에서 타겟이란 실행 파일이나 라이브러리 같은 빌드의 최종 결과물을 말한다. cmake는 실행하면 여러 파일과 디렉토리가 자동 생성되므로 build 디렉토리를 따로 만들어 그 안에서 실행하자.

한 줄짜리 CMakeLists.txt로 빌드했는데 많은 것들이 생겼다. 각각의 파일을 열어 어떻게 생겼는지 구경해보자. 간단한 프로젝트 인데도 상당히 복잡한 파일들이 생성된 것을 볼 수 있다. 프로젝트가 커져도 온갖 상황에 대처할 수 있게 설계하다보니 기본 설정이 다소 많은듯 하다.

 

CMakeCache.txt는 빌드 설정 변수들을 모아놓은 것인데 일반 에디터에서 열어서 수정해도 되지만 cmake-gui 툴을 이용하면 편하고 안전하게 수정할 수 있다. 설치는 sudo apt install cmake-qt-gui로 하면 된다. 주로 외부 라이브러리 경로를 자동으로 못 찾을 때 이 파일에서 수동으로 지정해준 후 다시 cmake를 하면 잘 된다. 사실 나머지 파일/디렉토리는 사용자가 열어볼 필요가 없다. 사용자는 일단 CMakeLists.txt를 잘 작성하는 것이 중요하다. 위 예시는 간단한 예제였고 실제로는 좀 더 자세한 설정이 필요하다.


 

엄청 자세한 설명

 

[C++] CMake Build System « IanFlow

1. Linux Build System C언어를 처음 배울 때 보통 Visual Studio에서 시작하는 경우가 많다. Visual Studio(이하 VS)는 통합개발환경(IDE)라서 VS에서 코딩도하고 컴파일 빌드 디버깅 실행 모두가 가능하다. 하지

goodgodgd.github.io

 

'IT > Linux' 카테고리의 다른 글

cmake option  (0) 2020.09.28
make install  (0) 2020.09.28
cmake 과정  (0) 2020.09.28
vi 편집기 검색, 하이라이트 설정  (0) 2020.09.28
vi 편집기 라인 복사  (0) 2020.09.28