오늘은 CMake를 사용하는 방법을 배우고 숙달하는 과정을 기록한다.
먼저 CMake란?
복잡한 소프트웨어 프로젝트의 빌드 과정을 자동으로 관리해주는 크로스 플랫폼 빌드 시스템 생성기이다. 다양한 OS와 컴파일러 환경에서 일관된 방식으로 프로젝트를 컴파일하고 빌드할 수 있게 도와준다.
앞의 설명만 보면 한 번에 이해하기 어려울 수 있다. 터미널에서 .cpp 확장자의 파일을 빌드하여 실행파일로 만드는 과정으로 설명해보겠다.
// main.cpp
#include <iostream>
using namespace std;
int main(void)
{
cout<<"Test!";
return 0;
}
위와 같은 main.cpp 파일을 빌드하려면 아래와 같은 명령어를 사용한다.
g++ -o main main.cpp
그냥 단순히 저렇게만 실행하고, 생성된 main 파일을 실행하면 끝이다.
위에서 설명한 예는 하나의 파일만 빌드 후 실행하는 과정이라 굉장히 단순하다.
하지만 프로젝트의 사이즈가 커지면, 여러 의존성도 많아지게 되고, 파일의 수도 많아지게 된다. 빌드하고, 링킹하고.. 이러한 과정을 수작업으로 할 수는 없다.
그래서 사용하는게 makefile인데, 이러한 makefile을 자동으로 작성할 수 있도록 돕는게 CMake이다.
CMake 사용하기
빌드에 필요한 파일들 작성하기
먼저 프로젝트 workspace를 만들고, workspace 하위에 build src include 라는 디렉터리를 만들 것이다. 추가적으로 main.cpp, myArray.cpp, myArray.hpp 그리고 CMakeLists.txt라는 파일을 생성한다.
├── build
├── CMakeLists.txt
├── include
│ └── myArray.hpp
└── src
├── main.cpp
└── myArray.cpp
각 파일에 대해 설명하자면, myArray.cpp에는 배열의 포인터와 배열의 크기를 입력 받으면 배열의 요소를 출력하는 함수가 존재한다. myArray.hpp에는 이 함수의 정의가 있다.
main.cpp에서는 myArray.hpp를 헤더 파일로 포함하여 배열을 출력하는 함수를 실행하는 main 코드이다.
각 코드의 내용은 아래와 같다.
// myArray.hpp
#include <iostream>
void each_for_array(int *arr, size_t size);
// myArray.cpp
#include <iostream>
#include "myArray.hpp"
using namespace std;
void each_for_array(int *arr, size_t size)
{
cout<<"===Print Array===\n";
for(size_t i=0; i<size ; i++)
{
cout<<arr[i]<<" ";
}
cout<<"\n===Print Array End===\n";
}
// main.cpp
#include <iostream>
#include "myArray.hpp"
using namespace std;
int main()
{
int array[]={2, 4, 6, 7, 8};
each_for_array(array, sizeof(array) / sizeof(array[0]));
return 0;
}
위와 같이 코드를 모두 작성한 후, 빌드를 위한 CMakeLists.txt라는 파일의 내용을 채우는 단계를 거친다.
CMakeLists.txt 작성
# CMake의 최소 버전
cmake_minimum_required(VERSION 3.24)
# 프로젝트의 이름과 사용할 언어를 정의한다.
project(
print_array
CXX
C
)
# C++ 표준을 C++17로 설정한다.
set(CMAKE_CXX_STANDARD 17)
# C++ 표준을 반드시 C++17로 설정한다.
set(CMAKE_CXX_STANDARD_REQUIRED True)
# print_array_app이라는 이름의 실행 파일을 생성하도록 CMake에 지시한다.
# 실행 파일을 빌드하기 위해 필요한 소스 파일 목록을 지정한다.
add_executable(
print_array_app
src/main.cpp
src/myArray.cpp
)
# 특정 타겟("print_array_app")에 헤더 파일을 찾을 경로를 추가한다.
target_include_directories(
print_array_app
# PUBLIC 키워드는 이 타겟을 사용하는 다른 타겟도 이 경로를 상속받게 한다.
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include
)
CMakeLists.txt 파일의 내용은 각 주석으로 설명해두었다.
이렇게 모든 파일을 작성하면 빌드 준비가 된 것이다. 디렉터리와 파일들의 구조와 아래와 같이 되어 있어야 한다.
.
├── build
├── CMakeLists.txt
├── include
│ └── myArray.hpp
└── src
├── main.cpp
└── myArray.cpp
cd build && cmake ..
위 명령어를 수행 후 tree를 입력하면 아래와 같은 파일 구조로 바뀔 것이다.

많은 파일들이 생성되었지만 핵심적으로 우리가 사용할 파일은 build/Makefile 이다.
위에서 말했듯이 cmake는 Makefile을 자동으로 작성할 수 있도록 돕는 도구라고 했다. Makefile의 내용을 한 번 살펴보도록 하고, 그 후에 Makefile과 같은 경로에서 아래와 같은 명령어를 수행한다.
make
# 수행 결과 예시
[ 33%] Building CXX object CMakeFiles/print_array_app.dir/src/main.cpp.o
[ 66%] Building CXX object CMakeFiles/print_array_app.dir/src/myArray.cpp.o
[100%] Linking CXX executable print_array_app
[100%] Built target print_array_app
print_array_app이 빌드되었다는 메시지를 확인할 수 있고, 실제로 파일들 목록을 출력해보면 실행 파일이 생성되어 있는 것을 확인할 수 있다.

실행 파일을 실행하면 정상적으로 실행할 수 있는 것을 확인할 수 있다.

이것으로 cmake 사용해보기 실습을 마친다.
'공부 일지 + 일상' 카테고리의 다른 글
| [ AWS AI & CLOUD 활용 과정 후기 ] (3) | 2024.12.28 |
|---|---|
| [Windows 11 Camera 오류 해결] 0xA00F429E (0) | 2024.10.17 |