빌드 자동화 툴 Cmake에 관한 설명과 사용법을 알아보도록 하겠습니다.
Cmake를 사용하는 이유
Cmake는 Makefile을 만들어주는 툴입니다.
Cmake를 설명하기 전에 Makefile이 무엇이냐면 빌드를 편리하게 해주는 일종의 빌드 스크립트라고 보시면 됩니다. 이 스크립트를 make명령을 사용해서 실행시키기는 겁니다.
그냥 shell파일을 이용해서 빌드를 할 수 있겠지만 Makefile을 사용하는 이유는 Incremental build의 방식을 사용하기 때문입니다.
Incremental build란?
프로젝트의 규모가 커질수록 수많은 소스 파일들이 생겨날테고, 빌드하는 시간도 오래걸리게 됩니다. 우리가 대학교에서 프로젝트하는 수준은 그냥 강아지 애교 수준이고 정말 회사에서 일하게 될 경우에는 빌드하는 것도 시간이 꽤 걸립니다.
그래서 우선 처음에는 모두 빌드를 해놓고, 그 이후 수정된 파일에 대해서는 그 소스파일과 연관된 것들만 빌드하여 시간을 줄여주는 빌드 방식이라고 생각하시면 됩니다.
이러한 편리성이 존재하지만 Make는 의존성에 관한 기술을 일일이 기재해야 되기 때문에 관리측면에서 번거롭습니다.
Cmake는 이런 귀찮은 점을 해결해주는 툴로서 Makefile 생성해내는 역할을 합니다.
간단하게 Cmake를 사용하는 방법을 알아보도록 하겠습니다.
a.c
int add(int a,int b){
return a+b;
}
a.h
int add(int,int);
b.c
#include <stdio.h>
#include "a.h"
int main(){
printf("%d+%d=%d\n",5,6,add(5,6));
return 0;
}
a.c는 add라는 함수가 존재하고 단지 두 수를 더해서 결과를 return하는 함수입니다.
a.h는 a.c의 함수를 선언한 헤더파일이고 b.c는 a.h의 함수를 사용하는 실제 프로그램입니다.
이 간단한 프로그램을 빌드하는 CMakeLists.txt 작성은 단 한 줄이면 됩니다.
CMakeLists.txt
ADD_EXECUTABLE(a.out a.c b.c)
ADD_EXECUTABLE은 실행할 파일을 생성하는 명령으로 첫 번째 기재할 내용은 실행파일 이름이고 나머지는 그 실행파일을 생성하기 위한 source파일입니다.
이제 아래의 명령을 통해서 실행해보도록 합시다.
cmake CMakeLists.txt
#cmake CMakeLists.txt -- The C compiler identification is GNU 5.5.0 -- The CXX compiler identification is GNU 5.5.0 -- Check for working C compiler: /usr/bin/cc -- Check for working C compiler: /usr/bin/cc -- works -- Detecting C compiler ABI info -- Detecting C compiler ABI info - done -- Detecting C compile features -- Detecting C compile features - done -- Check for working CXX compiler: /usr/bin/c++ -- Check for working CXX compiler: /usr/bin/c++ -- works -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Detecting CXX compile features -- Detecting CXX compile features - done -- Configuring done -- Generating done # ls a.c a.h a.out b.c CMakeCache.txt CMakeFiles cmake_install.cmake CMakeLists.txt Makefile |
그러면 소스파일 외에도 Cmake와 관련된 파일이 생성되는데, Makefile도 추가로 포함되었음을 알 수 있습니다.
만약 cmake가 없었다면 Makefile의 내용은 여러분들이 작성했어야하겠죠?
Cmake를 이용하면 간단하게 한 줄이면 되니까 무척이나 편리합니다.
이제 실제 make를 실행하면 우리가 만들어내고 싶은 a.out이라는 실행파일이 만들어집니다.
# make [ 33%] Building C object CMakeFiles/a.out.dir/a.c.o [ 66%] Building C object CMakeFiles/a.out.dir/b.c.o [100%] Linking C executable a.out [100%] Built target a.out # ls a.c a.h a.out b.c CMakeCache.txt CMakeFiles cmake_install.cmake CMakeLists.txt Makefile # ./a.out 5+6=11 |
Cmake는 변수 선언도 가능하며 다양한 명령어가 존재합니다. 이런 명령어들은 대, 소문자를 구분하지 않지만 보편적으로 대문자를 사용합니다.
CMAKE_MINIMUM_REQUIRED()
Cmake빌드를 실행할 최소 버전을 명시합니다. 보통 맨 위에 사용하며 기재된 버전보다 낮다면 오류를 보여주고 빌드를 종료합니다.
사용법은 아래와 같습니다.
CMAKE_MINIMUM_REQUIRED( VERSION 3.4.3 )
SET() 변수 정의
SET명령어는 변수를 정의하며 다음과 같이 사용됩니다.
SET(변수명 값)
어렵지 않죠? 뿐만 아니라 List형식으로도 변수를 정의할 수도 있습니다.
SET(변수명 값1 값2 값3)
이렇게 정의된 변수는 $변수, 혹는 "{}"를 써서 ${변수}로 사용할 수 있습니다.
앞의 CMakeLists.txt를 변수를 통해 바꿔본다면 이렇게 바꿀 수 있습니다.
SET(SRC_FILES a.c b.c)
SET(BIN_NAME a.out)
ADD_EXECUTABLE(${BIN_NAME} ${SRC_FILES})
PROJECT() 프로젝트명 정의
PROJECT(프로젝트 명)으로 쓰이게 되고 프로젝트의 이름을 정해주는 명령어로 CMAKE_PROJECT_NAME이라는 변수에 저장이 됩니다.
MESSAGE() 메시지 출력
혹시 변수에 들어있는 값이라던가 오류 메시지를 표시하려면 MESSAGE라는 명령어를 사용하여 출력하면 됩니다.
MESSAGE( TYPE MESSAGE)
메시지 종류는 생략가능하며 5가지의 종류가 있습니다. STATUS가 가장 심각도가 약한 단계이고 FATAL_ERROR가 심각도가 가장 심합니다.
TYPE | 설명 |
STATUS | 상태 메시지 출력, 계속 진행 |
WARNING | 경고 메시지를 출력, 계속 진행 |
AUTHOR_WARNING | 프로젝트 개발자용 경고 메시지를 출력, 계속 진행 |
SEND_ERROR | 오류 메시지를 출력, 계속 진행, Makefile생성하지 않음 |
FATAL_ERROR | 오류 메시지를 출력, 작업 중단 |
ADD_LIBRARY()
ADD_LIBRARY는 실행파일이 아닌 library파일을 생성할 때 쓰이는 명령입니다. 아래와 같이 쓰이게 되죠.
ADD_LIBRARY( library이름 TYPE 파일1 파일2 …)
처음에는 라이브러리 이름이 쓰이고 두번째는 라이브러리의 종류를 나타냅니다. Default로 STATIC이 쓰이며 아래와 같이 3개의 종류 중 하나를 지정할 수 있습니다.
STATIC, SHARED, MODULE
그리고 난 후에는 사용될 파일을 쭉 나열하면 됩니다.
위의 CMakeLists.txt를 수정하여 소스파일 a의 공유 라이브러리를 만든다면 아래와 같이 수정하시면 됩니다.
SET(SRC_FILES a.c)
SET(LIB_NAME a)
ADD_LIBRARY(${LIB_NAME} SHARED ${SRC_FILES})
후에 빌드하면 lib(라이브러리 이름).so 파일이 생기는 것을 확인할 수 있습니다.
ADD_DEFINITIONS()
전처리시에 정의할 매크로를 의미합니다. 앞에 -D를 쓰고 나서 매크로명을 써야하며 #define 의 구문의 역할을 한다고 보시면 됩니다. 2가지 사용법이 있습니다. 컴파일시에 -D매크로명 옵션과 같습니다.
ADD_DEFINITIONS(-D매크로명) : 단순 define으로 매크로를 정의할때 사용합니다.
ADD_DEFINITIONS(-D매크로명=값) : 매크로에 값을 집어넣습니다.
INCLUDE_DIRECTORIES()
#include에서 사용할 디렉토리를 명시합니다. 만약 inc 디렉토리에 헤더파일이 존재하는 경우 아래와 같이 사용하면 됩니다.
INCLUDE_DIRECTORIES(inc)
이상 간단하게 CMake의 개념과 사용법을 알아보았습니다. 다음에는 더 심도있게 알아보도록 하겠습니다.
'컴퓨터 > 운영체제(주로 리눅스)' 카테고리의 다른 글
[리눅스] 커널(kernel)과 쉘(shell)의 개념, 쉘을 이해해보자 (0) | 2021.03.07 |
---|---|
[운영체제] 스케줄링(Scheduling) 알고리즘(FIFO, SJF, 우선순위, Round-robin) (2) | 2021.03.01 |
[운영체제/리눅스] 교착상태(deadlock)의 원인과 쓰레드를 통한 교착상태 발생 예제와 회피방법(pthread_mutex_timed_lock) (0) | 2020.12.31 |
[리눅스] 정적라이브러리 작성, 공유 라이브러리 작성, 차이점 보기 (1) | 2020.12.28 |
[리눅스] 데몬 기초 : 개념과 구현 방법 (0) | 2020.12.19 |