Ver2.0 ๐ ๏ธ ๋น๋ ์์คํ : CMake ์ฌ์ฉ๋ฒ ๋ง์คํฐํ๊ธฐ ๐ ๏ธ

์๋ ? ์ค๋์ C++ ๊ฐ๋ฐ์๋ผ๋ฉด ๊ผญ ์์์ผ ํ CMake์ ๋ํด ํจ๊ป ์์๋ณด์! ํ๋ก์ ํธ๊ฐ ์ปค์ง์๋ก ์์ค ํ์ผ ๊ด๋ฆฌ์ ๋น๋ ๊ณผ์ ์ด ๋ณต์กํด์ง๋ ๊ฑด ๋น์ฐํ ์ผ์ด์ง. ๊ทธ๋ด ๋ CMake ๊ฐ์ ๋น๋ ์์คํ ์ด ์ฐ๋ฆฌ์ ๊ตฌ์์๊ฐ ๋์ด์ค ๊ฑฐ์ผ. ๐
๋ด๊ฐ ์ฌ๋ฅ๋ท์์ ํ๋ก๊ทธ๋๋ฐ ๊ฐ์๋ฅผ ์งํํ๋ฉด์ ๊ฐ์ฅ ๋ง์ด ๋ฐ๋ ์ง๋ฌธ ์ค ํ๋๊ฐ ๋ฐ๋ก "๋น๋ ์์คํ ์ ์ด๋ป๊ฒ ๊ตฌ์ฑํ๋์?"์ผ. ํนํ C++ ํ๋ก์ ํธ์์ ์ด ๋ถ๋ถ์ ์ ๋ง ์ค์ํ๊ฑฐ๋ . ์ค๋ ์ด ๊ธ์ ํตํด ๊ทธ ํด๋ต์ ์ฐพ์๋ณด์!
๐ค ์ CMake๋ฅผ ์ฌ์ฉํด์ผ ํ ๊น?
C++ ํ๋ก์ ํธ๋ฅผ ๊ฐ๋ฐํ ๋ ๊ทธ๋ฅ IDE์ '๋น๋' ๋ฒํผ๋ง ๋๋ฅด๋ฉด ๋๋ ๊ฑฐ ์๋๋๊ณ ? ์... ์์ ํ๋ก์ ํธ๋ผ๋ฉด ๊ทธ๋๋ ๊ด์ฐฎ์ ์ ์์ด. ํ์ง๋ง ํ๋ก์ ํธ๊ฐ ์ปค์ง๋ฉด ๋ค์๊ณผ ๊ฐ์ ๋ฌธ์ ๋ค์ด ์๊ฒจ:
- ์ฌ๋ฌ ํ๋ซํผ(Windows, Linux, macOS)์์ ๋์ํด์ผ ํ ๋
- ๋ค์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์์กด์ฑ์ ๊ด๋ฆฌํด์ผ ํ ๋
- ํ ๋จ์๋ก ๊ฐ๋ฐํ ๋ ๋ชจ๋ ๊ฐ๋ฐ์๊ฐ ๋์ผํ ํ๊ฒฝ์์ ๋น๋ํด์ผ ํ ๋
- CI/CD ํ์ดํ๋ผ์ธ์ ๊ตฌ์ถํ ๋
- ๋น๋ ์ต์ ์ ์ธ๋ฐํ๊ฒ ์ ์ดํด์ผ ํ ๋
CMake๋ ์ด๋ฐ ๋ฌธ์ ๋ค์ ํด๊ฒฐํด์ฃผ๋ ํฌ๋ก์ค ํ๋ซํผ ๋น๋ ์์คํ ์์ฑ๊ธฐ์ผ. ํ ๋ฒ CMake ์ค์ ํ์ผ์ ์์ฑํ๋ฉด, ์ด๋ค ํ๋ซํผ์์๋ ํ์ํ ๋น๋ ํ์ผ(Makefile, Visual Studio ํ๋ก์ ํธ ๋ฑ)์ ์๋์ผ๋ก ์์ฑํด์ค. ์ ๋ง ํธ๋ฆฌํ์ง? ๐
๐ CMake ๊ฐ์
CMake๋ 1999๋ ์ ์ฒ์ ๋ฑ์ฅํ์ด. ์ฒ์์๋ ๋จ์ํ ๋น๋ ๋๊ตฌ์์ง๋ง, ์ง๊ธ์ C++๋ฟ๋ง ์๋๋ผ ๋ค์ํ ์ธ์ด์ ํ๋ก์ ํธ๋ฅผ ๊ด๋ฆฌํ๋ ๊ฐ๋ ฅํ ๋๊ตฌ๋ก ๋ฐ์ ํ์ง. ํนํ C++ ํ์ค์ด ๊ณ์ ๋ฐ์ ํ๋ฉด์ CMake๋ ํจ๊ป ์งํํด์์ด. ํ์ฌ๋ ๋ฒ์ 3.x๋๋ฅผ ์ฌ์ฉํ๊ณ ์๊ณ , ์ต์ C++ ํ์ค๊ณผ ๋ค์ํ ๋น๋ ํ๊ฒฝ์ ์๋ฒฝํ๊ฒ ์ง์ํด.
CMake์ ํต์ฌ ๊ฐ๋ ์ ๋ค์๊ณผ ๊ฐ์:
- CMakeLists.txt: ํ๋ก์ ํธ ๊ตฌ์ฑ์ ์ ์ํ๋ ํต์ฌ ํ์ผ
- ํ๊ฒ(Target): ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ์คํ ํ์ผ๊ณผ ๊ฐ์ ๋น๋ ๊ฒฐ๊ณผ๋ฌผ
- ๋ณ์(Variable): CMake ๋ด์์ ์ ๋ณด๋ฅผ ์ ์ฅํ๊ณ ์ฐธ์กฐํ๋ ๋ฐฉ๋ฒ
- ๋ช ๋ น์ด(Command): CMake ์คํฌ๋ฆฝํธ์์ ์ฌ์ฉํ๋ ํจ์๋ค
- ๋ชจ๋(Module): ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ CMake ์คํฌ๋ฆฝํธ ๋ชจ์
โ๏ธ CMake ์ค์นํ๊ธฐ
CMake๋ฅผ ์ฌ์ฉํ๊ธฐ ์ ์ ๋จผ์ ์ค์นํด์ผ ํ๊ฒ ์ง? ๊ฐ ์ด์์ฒด์ ๋ณ ์ค์น ๋ฐฉ๋ฒ์ ์์๋ณด์:
Windows
Windows์์๋ ๊ณต์ ์น์ฌ์ดํธ์์ ์ธ์คํจ๋ฌ๋ฅผ ๋ค์ด๋ก๋ํ๊ฑฐ๋ ํจํค์ง ๊ด๋ฆฌ์๋ฅผ ์ฌ์ฉํ ์ ์์ด:
choco install cmake
๋๋
winget install Kitware.CMake
macOS
macOS์์๋ Homebrew๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ๊ฐ์ฅ ๊ฐํธํด:
brew install cmake
Linux
Ubuntu๋ Debian ๊ธฐ๋ฐ ๋ฐฐํฌํ์์๋:
sudo apt-get install cmake
Fedora๋ RHEL ๊ธฐ๋ฐ ๋ฐฐํฌํ์์๋:
sudo dnf install cmake
์ค์น๊ฐ ์๋ฃ๋๋ฉด ํฐ๋ฏธ๋์์ ๋ค์ ๋ช ๋ น์ด๋ก CMake๊ฐ ์ ๋๋ก ์ค์น๋์๋์ง ํ์ธํด๋ณด์:
cmake --version
์ต์ ๋ฒ์ ์ CMake๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ์ข์. ์ต์ํ ๋ฒ์ 3.10 ์ด์์ ๊ถ์ฅํด! ์ต์ C++ ํ์ค๊ณผ ๋ค์ํ ๊ธฐ๋ฅ์ ์ง์ํ๊ฑฐ๋ . ๐
๐ ์ฒซ ๋ฒ์งธ CMake ํ๋ก์ ํธ
์ด๋ก ์ ์ถฉ๋ถํด! ์ด์ ์ค์ ๋ก CMake๋ฅผ ์ฌ์ฉํด์ ๊ฐ๋จํ C++ ํ๋ก์ ํธ๋ฅผ ๋น๋ํด๋ณด์. ๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ "Hello, World!" ํ๋ก๊ทธ๋จ๋ถํฐ ์์ํ ๊ฒ. ๐
ํ๋ก์ ํธ ๊ตฌ์กฐ
๋จผ์ ๋ค์๊ณผ ๊ฐ์ ๋๋ ํ ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ๋ง๋ค์ด๋ณด์:
hello_cmake/
โโโ CMakeLists.txt
โโโ main.cpp
main.cpp
๊ฐ์ฅ ๊ฐ๋จํ C++ ์ฝ๋๋ฅผ ์์ฑํด๋ณด์:
#include <iostream>
int main() {
std::cout << "Hello, CMake World!" << std::endl;
return 0;
}
CMakeLists.txt
์ด์ CMake ์ค์ ํ์ผ์ ์์ฑํด๋ณด์:
cmake_minimum_required(VERSION 3.10)
# ํ๋ก์ ํธ ์ด๋ฆ ์ค์
project(HelloCMake VERSION 1.0)
# C++ ํ์ค ์ค์
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# ์คํ ํ์ผ ํ๊ฒ ์ถ๊ฐ
add_executable(hello_cmake main.cpp)
๊ฐ ์ค์ด ๋ฌด์จ ์๋ฏธ์ธ์ง ์ดํด๋ณด์:
cmake_minimum_required: ํ์ํ ์ต์ CMake ๋ฒ์ ์ ์ง์ ํดproject: ํ๋ก์ ํธ ์ด๋ฆ๊ณผ ๋ฒ์ ์ ์ค์ ํดset(CMAKE_CXX_STANDARD 17): C++17 ํ์ค์ ์ฌ์ฉํ๋๋ก ์ค์ ํดadd_executable: ์คํ ํ์ผ์ ๋ง๋ค๊ณ , ํ์ํ ์์ค ํ์ผ์ ์ง์ ํด
ํ๋ก์ ํธ ๋น๋ํ๊ธฐ
์ด์ ํ๋ก์ ํธ๋ฅผ ๋น๋ํด๋ณด์. CMake๋ ์์ค ๋๋ ํ ๋ฆฌ์ ๋ณ๋๋ก ๋น๋ ๋๋ ํ ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๊ถ์ฅํด. ์ด๋ฅผ "out-of-source build"๋ผ๊ณ ๋ถ๋ฌ. ์ด๋ ๊ฒ ํ๋ฉด ์์ค ์ฝ๋์ ๋น๋ ๊ฒฐ๊ณผ๋ฌผ์ด ์์ด์ง ์์์ ๊ด๋ฆฌํ๊ธฐ ํธํด์ ธ. ๐
ํฐ๋ฏธ๋์์ ๋ค์ ๋ช ๋ น์ด๋ฅผ ์คํํด๋ณด์:
# ๋น๋ ๋๋ ํ ๋ฆฌ ์์ฑ
mkdir build
cd build
# CMake ๊ตฌ์ฑ
cmake ..
# ๋น๋ ์คํ
cmake --build .
๋น๋๊ฐ ์ฑ๊ณต์ ์ผ๋ก ์๋ฃ๋๋ฉด build ๋๋ ํ ๋ฆฌ ์์ hello_cmake(Windows์์๋ hello_cmake.exe) ์คํ ํ์ผ์ด ์์ฑ๋ผ. ์ด์ ์คํํด๋ณด์:
./hello_cmake
ํฐ๋ฏธ๋์ "Hello, CMake World!"๊ฐ ์ถ๋ ฅ๋๋ฉด ์ฑ๊ณต์ด์ผ! ๐
๐ ์ฃผ์ CMake ๋ช ๋ น์ด
CMake์๋ ๋ค์ํ ๋ช ๋ น์ด๊ฐ ์์ด. ์์ฃผ ์ฌ์ฉํ๋ ์ค์ํ ๋ช ๋ น์ด๋ค์ ์์๋ณด์:
์ด ์ธ์๋ ๋ง์ ๋ช ๋ น์ด๊ฐ ์์ง๋ง, ์์ ๋ช ๋ น์ด๋ค๋ง ์์๋ ๊ธฐ๋ณธ์ ์ธ CMake ํ๋ก์ ํธ๋ ์ถฉ๋ถํ ๊ตฌ์ฑํ ์ ์์ด. ํนํ target_link_libraries์ target_include_directories๋ ํ๋์ ์ธ CMake์์ ๋งค์ฐ ์ค์ํ ๋ช ๋ น์ด์ผ. ์ด ๋ช ๋ น์ด๋ค์ ์ฌ์ฉํ๋ฉด ์์กด์ฑ์ ๋ช ํํ๊ฒ ๊ด๋ฆฌํ ์ ์๊ฑฐ๋ . ๐งฉ
๐ ์ฌ๋ฌ ํ์ผ๋ก ๊ตฌ์ฑ๋ ํ๋ก์ ํธ
์ค์ ํ๋ก์ ํธ๋ ๋๋ถ๋ถ ์ฌ๋ฌ ํ์ผ๋ก ๊ตฌ์ฑ๋์ด ์์ง. ์ด๋ฒ์๋ ์กฐ๊ธ ๋ ๋ณต์กํ ๊ตฌ์กฐ์ ํ๋ก์ ํธ๋ฅผ CMake๋ก ๊ด๋ฆฌํด๋ณด์.
ํ๋ก์ ํธ ๊ตฌ์กฐ
calculator/
โโโ CMakeLists.txt
โโโ include/
โ โโโ calculator/
โ โโโ add.h
โ โโโ subtract.h
โ โโโ multiply.h
โโโ src/
โ โโโ add.cpp
โ โโโ subtract.cpp
โ โโโ multiply.cpp
โ โโโ main.cpp
โโโ tests/
โโโ CMakeLists.txt
โโโ test_calculator.cpp
ํค๋ ํ์ผ
๊ฐ๋จํ ๊ณ์ฐ๊ธฐ ํจ์๋ฅผ ์ ์ํด๋ณด์:
include/calculator/add.h
#pragma once
namespace calculator {
int add(int a, int b);
}
include/calculator/subtract.h
#pragma once
namespace calculator {
int subtract(int a, int b);
}
include/calculator/multiply.h
#pragma once
namespace calculator {
int multiply(int a, int b);
}
์์ค ํ์ผ
src/add.cpp
#include "calculator/add.h"
namespace calculator {
int add(int a, int b) {
return a + b;
}
}
src/subtract.cpp
#include "calculator/subtract.h"
namespace calculator {
int subtract(int a, int b) {
return a - b;
}
}
src/multiply.cpp
#include "calculator/multiply.h"
namespace calculator {
int multiply(int a, int b) {
return a * b;
}
}
src/main.cpp
#include <iostream>
#include "calculator/add.h"
#include "calculator/subtract.h"
#include "calculator/multiply.h"
int main() {
std::cout << "10 + 5 = " << calculator::add(10, 5) << std::endl;
std::cout << "10 - 5 = " << calculator::subtract(10, 5) << std::endl;
std::cout << "10 * 5 = " << calculator::multiply(10, 5) << std::endl;
return 0;
}
ํ ์คํธ ํ์ผ
tests/test_calculator.cpp
#include <cassert>
#include <iostream>
#include "calculator/add.h"
#include "calculator/subtract.h"
#include "calculator/multiply.h"
int main() {
// ํ
์คํธ add
assert(calculator::add(5, 3) == 8);
// ํ
์คํธ subtract
assert(calculator::subtract(5, 3) == 2);
// ํ
์คํธ multiply
assert(calculator::multiply(5, 3) == 15);
std::cout << "๋ชจ๋ ํ
์คํธ ํต๊ณผ!" << std::endl;
return 0;
}
CMakeLists.txt
calculator/CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(Calculator VERSION 1.0)
# C++ ํ์ค ์ค์
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์์ค ํ์ผ ๋ชฉ๋ก
set(SOURCES
src/add.cpp
src/subtract.cpp
src/multiply.cpp
)
# ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์์ฑ
add_library(calculator_lib STATIC ${SOURCES})
# ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ include ๊ฒฝ๋ก ์ค์
target_include_directories(calculator_lib
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/include
)
# ์คํ ํ์ผ ์์ฑ
add_executable(calculator src/main.cpp)
# ์คํ ํ์ผ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋งํฌ
target_link_libraries(calculator
PRIVATE
calculator_lib
)
# ํ
์คํธ ๋๋ ํ ๋ฆฌ ์ถ๊ฐ
add_subdirectory(tests)
calculator/tests/CMakeLists.txt
# ํ
์คํธ ์คํ ํ์ผ ์์ฑ
add_executable(test_calculator test_calculator.cpp)
# ํ
์คํธ ์คํ ํ์ผ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋งํฌ
target_link_libraries(test_calculator
PRIVATE
calculator_lib
)
ํ๋ก์ ํธ ๋น๋ํ๊ธฐ
์ด์ ์ด ํ๋ก์ ํธ๋ฅผ ๋น๋ํด๋ณด์:
mkdir build
cd build
cmake ..
cmake --build .
๋น๋๊ฐ ์๋ฃ๋๋ฉด calculator ์คํ ํ์ผ๊ณผ test_calculator ํ
์คํธ ์คํ ํ์ผ์ด ์์ฑ๋ผ. ๊ฐ๊ฐ ์คํํด๋ณด์:
./calculator
./tests/test_calculator
์ด ์์ ์์๋ ์ ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ(STATIC)๋ฅผ ๋ง๋ค๊ณ , ๊ทธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์คํ ํ์ผ๊ณผ ํ
์คํธ ํ์ผ์ ๋งํฌํ์ด. ์ด๋ ๊ฒ ํ๋ฉด ์ฝ๋ ์ฌ์ฌ์ฉ์ฑ์ด ๋์์ง๊ณ , ํ๋ก์ ํธ ๊ตฌ์กฐ๊ฐ ๋ ๊น๋ํด์ ธ. ๋ํ add_subdirectory ๋ช
๋ น์ด๋ฅผ ์ฌ์ฉํด์ ํ
์คํธ ๋๋ ํ ๋ฆฌ์ CMakeLists.txt๋ ํจ๊ป ์ฒ๋ฆฌํ์ด. ๐งฑ
๐ ํ๋์ ์ธ CMake ์ฌ์ฉ๋ฒ
CMake๋ ์ค๋ ์ญ์ฌ๋ฅผ ๊ฐ์ง ๋๊ตฌ์ด๋ค ๋ณด๋, ์๊ฐ์ด ์ง๋๋ฉด์ ์ฌ์ฉ ๋ฐฉ์์ด ๋ง์ด ๋ณํํ์ด. ์ต๊ทผ์๋ "Modern CMake"๋ผ๊ณ ๋ถ๋ฆฌ๋ ์ ๊ทผ ๋ฐฉ์์ด ๊ถ์ฅ๋๊ณ ์์ด. ์ด ๋ฐฉ์์ ํต์ฌ์ "ํ๊ฒ ์ค์ฌ(target-centric)" ์ ๊ทผ๋ฒ์ด์ผ. ๐ฏ
ํ๊ฒ ์ค์ฌ ์ ๊ทผ๋ฒ
์ ํต์ ์ธ CMake์์๋ ์ ์ญ ๋ณ์์ ๋๋ ํ ๋ฆฌ ์์ฑ์ ๋ง์ด ์ฌ์ฉํ์ด:
# ์ ํต์ ์ธ ๋ฐฉ์ (๊ถ์ฅํ์ง ์์)
include_directories(include)
add_definitions(-DSOME_DEFINE)
link_libraries(some_lib)
add_executable(my_app main.cpp)
ํ์ง๋ง ํ๋์ ์ธ CMake์์๋ ๊ฐ ํ๊ฒ์ ์ง์ ์์ฑ์ ์ค์ ํด:
# ํ๋์ ์ธ ๋ฐฉ์ (๊ถ์ฅ)
add_executable(my_app main.cpp)
target_include_directories(my_app PRIVATE include)
target_compile_definitions(my_app PRIVATE SOME_DEFINE)
target_link_libraries(my_app PRIVATE some_lib)
์ด ๋ฐฉ์์ ์ฅ์ ์:
- ์์กด์ฑ์ด ๋ช ํํด์ง
- ์์ฑ์ ๋ฒ์(PRIVATE, PUBLIC, INTERFACE)๋ฅผ ๋ช ์์ ์ผ๋ก ์ง์ ํ ์ ์์
- ๋ถํ์ํ ์ ์ญ ์ํ๋ฅผ ํผํ ์ ์์
์ธํฐํ์ด์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ
ํ๋์ ์ธ CMake์์๋ INTERFACE ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํด ํค๋ ์ ์ฉ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ์ค์ ๋ชจ์์ ๋ง๋ค ์ ์์ด:
# ์ปดํ์ผ ์ต์
์ ๋ชจ์๋ ์ธํฐํ์ด์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ
add_library(project_options INTERFACE)
target_compile_features(project_options INTERFACE cxx_std_17)
target_compile_options(project_options INTERFACE -Wall -Wextra -Wpedantic)
# ๊ฒฝ๊ณ ๋ฅผ ์๋ฌ๋ก ์ทจ๊ธํ๋ ๋น๋ ํ์
์ค์
if(CMAKE_BUILD_TYPE STREQUAL "Release")
target_compile_options(project_options INTERFACE -Werror)
endif()
# ์ค์ ํ๊ฒ์ ์ต์
์ ์ฉ
add_executable(my_app main.cpp)
target_link_libraries(my_app PRIVATE project_options)
๊ฐ์ ธ์จ ํ๊ฒ ์ฌ์ฉํ๊ธฐ
์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ ๋๋ find_package๋ก ์ฐพ์ ํ๊ฒ์ ์ง์ ๋งํฌํ๋ ๊ฒ์ด ์ข์:
# Boost ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ฐพ๊ธฐ
find_package(Boost 1.70 REQUIRED COMPONENTS filesystem system)
add_executable(my_app main.cpp)
# ์ง์ Boost ํ๊ฒ ๋งํฌ
target_link_libraries(my_app PRIVATE
Boost::filesystem
Boost::system
)
์ฌ๋ฅ๋ท์์ C++ ๊ด๋ จ ๊ฐ์๋ฅผ ๋ค์ด๋ณด๋ฉด ์ด๋ฐ ํ๋์ ์ธ CMake ์ฌ์ฉ๋ฒ์ ๋ง์ด ๋ฐฐ์ธ ์ ์์ด. ์ค์ ์ ๊ณ์์๋ ์ด๋ฐ ๋ฐฉ์์ด ํ์ค์ผ๋ก ์๋ฆฌ์ก๊ณ ์์ง. ํนํ ๋๊ท๋ชจ ํ๋ก์ ํธ์์๋ ์ด๋ฐ ์ ๊ทผ๋ฒ์ด ์ฝ๋ ๊ด๋ฆฌ์ ๋น๋ ์ฑ๋ฅ์ ํฐ ๋์์ด ๋ผ. ๐
๐ ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ฌ์ฉํ๊ธฐ
์ค์ ํ๋ก์ ํธ์์๋ ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์์ฃผ ์ฌ์ฉํ๊ฒ ๋ผ. CMake์์๋ find_package ๋ช
๋ น์ด๋ฅผ ์ฌ์ฉํด ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฐพ๊ณ ์ฌ์ฉํ ์ ์์ด.
find_package ์ฌ์ฉํ๊ธฐ
์๋ฅผ ๋ค์ด, OpenCV ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ ํ๋ก์ ํธ๋ฅผ ๋ง๋ค์ด๋ณด์:
cmake_minimum_required(VERSION 3.10)
project(OpenCVExample VERSION 1.0)
# OpenCV ํจํค์ง ์ฐพ๊ธฐ
find_package(OpenCV REQUIRED)
# ์คํ ํ์ผ ์์ฑ
add_executable(image_processor main.cpp)
# OpenCV ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋งํฌ ๋ฐ include ๊ฒฝ๋ก ์ค์
target_link_libraries(image_processor PRIVATE ${OpenCV_LIBS})
target_include_directories(image_processor PRIVATE ${OpenCV_INCLUDE_DIRS})
์ฌ๊ธฐ์ REQUIRED ์ต์
์ ํจํค์ง๋ฅผ ์ฐพ์ง ๋ชปํ๋ฉด CMake ๊ตฌ์ฑ ๋จ๊ณ์์ ์ค๋ฅ๋ฅผ ๋ฐ์์์ผ. ์ด๋ ๊ฒ ํ๋ฉด ๋น๋ ์ ์ ์์กด์ฑ ๋ฌธ์ ๋ฅผ ๋นจ๋ฆฌ ๋ฐ๊ฒฌํ ์ ์์ง. ๐
FetchContent ์ฌ์ฉํ๊ธฐ
CMake 3.11๋ถํฐ๋ FetchContent ๋ชจ๋์ ์ฌ์ฉํด ๋น๋ ์์ ์ ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์๋์ผ๋ก ๋ค์ด๋ก๋ํ๊ณ ๋น๋ํ ์ ์์ด:
cmake_minimum_required(VERSION 3.14)
project(FetchExample VERSION 1.0)
include(FetchContent)
# Google Test ๋ค์ด๋ก๋
FetchContent_Declare(
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG release-1.11.0
)
# ๋ค์ด๋ก๋ํ ์ฝํ
์ธ ์ฌ์ฉ ๊ฐ๋ฅํ๊ฒ ๋ง๋ค๊ธฐ
FetchContent_MakeAvailable(googletest)
# ํ
์คํธ ์คํ ํ์ผ ์์ฑ
add_executable(my_tests tests.cpp)
# Google Test ๋งํฌ
target_link_libraries(my_tests PRIVATE gtest_main gmock)
์ด ๋ฐฉ์์ ์ฅ์ ์ ์ฌ์ฉ์๊ฐ ์ง์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ค์นํ์ง ์์๋ ๋๋ค๋ ๊ฑฐ์ผ. ํ๋ก์ ํธ๋ฅผ ํด๋ก ํ๊ณ ๋น๋ํ๊ธฐ๋ง ํ๋ฉด ํ์ํ ๋ชจ๋ ์์กด์ฑ์ด ์๋์ผ๋ก ์ฒ๋ฆฌ๋ผ. ๋จ์ ์ ๋งค๋ฒ ๋น๋ํ ๋๋ง๋ค ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ํจ๊ป ๋น๋ํด์ผ ํด์ ์๊ฐ์ด ๋ ๊ฑธ๋ฆด ์ ์๋ค๋ ์ ์ด์ผ. โฑ๏ธ
ํจํค์ง ๊ด๋ฆฌ์์ ํจ๊ป ์ฌ์ฉํ๊ธฐ
๋๊ท๋ชจ ํ๋ก์ ํธ์์๋ Conan์ด๋ vcpkg ๊ฐ์ C++ ํจํค์ง ๊ด๋ฆฌ์๋ฅผ CMake์ ํจ๊ป ์ฌ์ฉํ๋ ๊ฒฝ์ฐ๊ฐ ๋ง์. ์๋ฅผ ๋ค์ด, Conan์ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ์ดํด๋ณด์:
# conanfile.txt
[requires]
fmt/8.0.1
nlohmann_json/3.10.5
[generators]
cmake_find_package
๊ทธ๋ฆฌ๊ณ CMakeLists.txt์์:
cmake_minimum_required(VERSION 3.10)
project(ConanExample VERSION 1.0)
# Conan ํจํค์ง ๊ฒฝ๋ก ์ถ๊ฐ
list(APPEND CMAKE_MODULE_PATH ${CMAKE_BINARY_DIR})
# ํจํค์ง ์ฐพ๊ธฐ
find_package(fmt REQUIRED)
find_package(nlohmann_json REQUIRED)
add_executable(json_formatter main.cpp)
target_link_libraries(json_formatter PRIVATE
fmt::fmt
nlohmann_json::nlohmann_json
)
๋น๋ ์ ์ ๋ค์ ๋ช ๋ น์ด๋ก ์์กด์ฑ์ ์ค์นํด:
mkdir build && cd build
conan install .. --build=missing
cmake ..
cmake --build .
์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๊ด๋ฆฌ๋ ํ๋ก์ ํธ๊ฐ ์ปค์ง์๋ก ๋ ์ค์ํด์ ธ. ํนํ ์ฌ๋ฌ ํ๋ซํผ์์ ๋์ํด์ผ ํ๋ ํ๋ก์ ํธ๋ผ๋ฉด CMake์ ํจํค์ง ๊ด๋ฆฌ์์ ์กฐํฉ์ด ๋งค์ฐ ์ ์ฉํด. ์ฌ๋ฅ๋ท์์๋ ์ด๋ฐ ์ฃผ์ ์ ๊ฐ์๊ฐ ์ธ๊ธฐ๊ฐ ๋ง์. ์ค๋ฌด์์ ๊ผญ ํ์ํ ์คํฌ์ด๋๊น! ๐ฆ
๐ ํฌ๋ก์ค ํ๋ซํผ ๋น๋
CMake์ ๊ฐ์ฅ ํฐ ์ฅ์ ์ค ํ๋๋ ํฌ๋ก์ค ํ๋ซํผ ์ง์์ด์ผ. ๊ฐ์ ์์ค ์ฝ๋์ CMake ํ์ผ๋ก Windows, Linux, macOS ๋ฑ ๋ค์ํ ํ๋ซํผ์์ ๋น๋ํ ์ ์์ง.
ํ๋ซํผ๋ณ ์ค์
ํ๋ซํผ์ ๋ฐ๋ผ ๋ค๋ฅธ ์ค์ ์ด ํ์ํ ๋๋ ์กฐ๊ฑด๋ฌธ์ ์ฌ์ฉํ ์ ์์ด:
# ํ๋ซํผ ๊ฐ์ง
if(WIN32)
# Windows ์ ์ฉ ์ค์
add_definitions(-DWINDOWS_PLATFORM)
target_sources(my_app PRIVATE src/windows_specific.cpp)
elseif(APPLE)
# macOS ์ ์ฉ ์ค์
add_definitions(-DMACOS_PLATFORM)
target_sources(my_app PRIVATE src/macos_specific.cpp)
elseif(UNIX AND NOT APPLE)
# Linux ์ ์ฉ ์ค์
add_definitions(-DLINUX_PLATFORM)
target_sources(my_app PRIVATE src/linux_specific.cpp)
endif()
์ปดํ์ผ๋ฌ๋ณ ์ค์
์ปดํ์ผ๋ฌ์ ๋ฐ๋ผ ๋ค๋ฅธ ์ต์ ์ ์ค์ ํ ์๋ ์์ด:
# ์ปดํ์ผ๋ฌ ๊ฐ์ง
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
# MSVC ์ปดํ์ผ๋ฌ ์ต์
target_compile_options(my_app PRIVATE /W4 /WX)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
# GCC ์ปดํ์ผ๋ฌ ์ต์
target_compile_options(my_app PRIVATE -Wall -Wextra -Wpedantic)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
# Clang ์ปดํ์ผ๋ฌ ์ต์
target_compile_options(my_app PRIVATE -Wall -Wextra -Wpedantic)
endif()
์ ๋๋ ์ดํฐ ํํ์
๋ ๋ณต์กํ ์กฐ๊ฑด์ด ํ์ํ ๋๋ ์ ๋๋ ์ดํฐ ํํ์์ ์ฌ์ฉํ ์ ์์ด:
# ๋๋ฒ๊ทธ ๋ชจ๋์์๋ง ํน์ ์ต์
์ ์ฉ
target_compile_definitions(my_app PRIVATE
$<$<CONFIG:Debug>:DEBUG_MODE>
$<$<CONFIG:Release>:NDEBUG>
)
# ํน์ ์ปดํ์ผ๋ฌ์์๋ง ์ต์
์ ์ฉ
target_compile_options(my_app PRIVATE
$<$<CXX_COMPILER_ID:MSVC>:/W4>
$<$<OR:$<CXX_COMPILER_ID:GNU>,$<CXX_COMPILER_ID:Clang>>:-Wall>
)
์ ๋๋ ์ดํฐ ํํ์์ CMake์ ๊ฐ๋ ฅํ ๊ธฐ๋ฅ ์ค ํ๋์ผ. ๋น๋ ์์คํ ์์ฑ ์์ ์ ํ๊ฐ๋๋ ์กฐ๊ฑด์์ผ๋ก, ๋งค์ฐ ์ ์ฐํ ์ค์ ์ด ๊ฐ๋ฅํด. ๐
ํด์ฒด์ธ ํ์ผ
๋ค๋ฅธ ์ํคํ ์ฒ๋ฅผ ์ํ ํฌ๋ก์ค ์ปดํ์ผ์ ํ ๋๋ ํด์ฒด์ธ ํ์ผ์ ์ฌ์ฉํด:
# arm-linux.cmake
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
set(CMAKE_FIND_ROOT_PATH /usr/arm-linux-gnueabihf)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
์ด ํด์ฒด์ธ ํ์ผ์ ์ฌ์ฉํด ๋น๋ํ๋ ค๋ฉด:
cmake -DCMAKE_TOOLCHAIN_FILE=arm-linux.cmake ..
ํฌ๋ก์ค ํ๋ซํผ ๊ฐ๋ฐ์ ์ฝ์ง ์์ ์์ ์ด์ง๋ง, CMake๋ฅผ ์ฌ์ฉํ๋ฉด ๋ง์ ๋ถ๋ถ์ด ์๋ํ๋ผ. ํนํ ๊ฒ์ ๊ฐ๋ฐ์ด๋ ์๋ฒ ๋๋ ์์คํ ๊ฐ๋ฐ์ฒ๋ผ ์ฌ๋ฌ ํ๋ซํผ์ ์ง์ํด์ผ ํ๋ ํ๋ก์ ํธ์์ CMake๋ ํ์์ ์ธ ๋๊ตฌ์ผ. ์ฌ๋ฅ๋ท์์๋ ์ด๋ฐ ํฌ๋ก์ค ํ๋ซํผ ๊ฐ๋ฐ ๊ด๋ จ ๊ฐ์๊ฐ ์ธ๊ธฐ๊ฐ ๋ง์. ๐
๐งช ํ ์คํธ ์๋ํ
CMake๋ CTest๋ผ๋ ํ ์คํธ ํ๋ ์์ํฌ๋ฅผ ๋ด์ฅํ๊ณ ์์ด. ์ด๋ฅผ ์ฌ์ฉํ๋ฉด ํ ์คํธ๋ฅผ ์ฝ๊ฒ ์๋ํํ ์ ์์ง.
CTest ๊ธฐ๋ณธ ์ฌ์ฉ๋ฒ
CMakeLists.txt์ ๋ค์ ์ค์ ์ถ๊ฐํด:
enable_testing()
๊ทธ๋ฆฌ๊ณ ํ ์คํธ๋ฅผ ๋ฑ๋กํด:
add_test(NAME MyTest COMMAND my_test_executable)
๋น๋ ํ ํ ์คํธ๋ฅผ ์คํํ๋ ค๋ฉด:
cd build
ctest
Google Test ์ฐ๋
Google Test์ ํจ๊ป ์ฌ์ฉํ๋ฉด ๋ ๊ฐ๋ ฅํ ํ ์คํธ ํ๊ฒฝ์ ๊ตฌ์ถํ ์ ์์ด:
cmake_minimum_required(VERSION 3.14)
project(TestExample VERSION 1.0)
# Google Test ๊ฐ์ ธ์ค๊ธฐ
include(FetchContent)
FetchContent_Declare(
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG release-1.11.0
)
FetchContent_MakeAvailable(googletest)
# ํ
์คํธ ํ์ฑํ
enable_testing()
# ํ
์คํธ ์คํ ํ์ผ ์์ฑ
add_executable(math_tests math_tests.cpp)
target_link_libraries(math_tests PRIVATE gtest_main)
# Google Test ํ
์คํธ ๋ฑ๋ก
include(GoogleTest)
gtest_discover_tests(math_tests)
gtest_discover_tests ํจ์๋ Google Test ์คํ ํ์ผ์์ ๋ชจ๋ ํ
์คํธ๋ฅผ ์๋์ผ๋ก ์ฐพ์์ CTest์ ๋ฑ๋กํด์ค. ์ด๋ ๊ฒ ํ๋ฉด ๊ฐ ํ
์คํธ ์ผ์ด์ค๊ฐ ๊ฐ๋ณ์ ์ผ๋ก CTest์ ํ์๋ผ. ๐
์ฝ๋ ์ปค๋ฒ๋ฆฌ์ง ์ธก์
CMake์ ํจ๊ป gcov/lcov๋ฅผ ์ฌ์ฉํด ์ฝ๋ ์ปค๋ฒ๋ฆฌ์ง๋ฅผ ์ธก์ ํ ์๋ ์์ด:
# ์ปค๋ฒ๋ฆฌ์ง ์ธก์ ์ ์ํ ์ปดํ์ผ ์ต์
์ค์
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage")
# ํ
์คํธ ์คํ ํ์ผ ์์ฑ
add_executable(math_tests math_tests.cpp)
target_link_libraries(math_tests PRIVATE gtest_main --coverage)
# ์ปค๋ฒ๋ฆฌ์ง ๋ฆฌํฌํธ ์์ฑ์ ์ํ ์ฌ์ฉ์ ์ ์ ํ๊ฒ
add_custom_target(coverage
COMMAND lcov --capture --directory . --output-file coverage.info
COMMAND lcov --remove coverage.info '/usr/*' --output-file coverage.info
COMMAND genhtml coverage.info --output-directory coverage_report
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
COMMENT "Generating code coverage report"
)
๋น๋ ํ ๋ค์ ๋ช ๋ น์ด๋ก ์ปค๋ฒ๋ฆฌ์ง ๋ฆฌํฌํธ๋ฅผ ์์ฑํ ์ ์์ด:
cd build
cmake --build . --target coverage
ํ ์คํธ ์๋ํ๋ ํ๋ ์ํํธ์จ์ด ๊ฐ๋ฐ์์ ๋งค์ฐ ์ค์ํ ๋ถ๋ถ์ด์ผ. CMake์ CTest๋ฅผ ์ฌ์ฉํ๋ฉด ๋น๋ ํ๋ก์ธ์ค์ ํ ์คํธ๋ฅผ ํตํฉํด์ ์ฝ๋ ํ์ง์ ์ง์์ ์ผ๋ก ๊ด๋ฆฌํ ์ ์์ด. ์ฌ๋ฅ๋ท์์๋ TDD(ํ ์คํธ ์ฃผ๋ ๊ฐ๋ฐ) ๊ด๋ จ ๊ฐ์๊ฐ ์ธ๊ธฐ๊ฐ ๋ง์. ์ค๋ฌด์์ ์ ๋ง ์ค์ํ ์คํฌ์ด๋๊น! ๐งช
โ CMake ๋ชจ๋ฒ ์ฌ๋ก
์ง๊ธ๊น์ง CMake์ ๋ค์ํ ๊ธฐ๋ฅ์ ์ดํด๋ดค์ด. ์ด์ ์ค์ ํ๋ก์ ํธ์์ CMake๋ฅผ ํจ๊ณผ์ ์ผ๋ก ์ฌ์ฉํ๊ธฐ ์ํ ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ์์๋ณด์.
์ด๋ฐ ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ๋ฐ๋ฅด๋ฉด CMake ํ๋ก์ ํธ๋ฅผ ๋ ๊น๋ํ๊ณ ์ ์ง๋ณด์ํ๊ธฐ ์ฝ๊ฒ ๋ง๋ค ์ ์์ด. ํนํ ํ๊ฒ ์ค์ฌ ์ ๊ทผ๋ฒ๊ณผ ์ ์ ํ ๋ฒ์ ์ง์ ์ ์ฌ์ฉ์ ํ๋์ ์ธ CMake์ ํต์ฌ์ด์ผ. ์ฌ๋ฅ๋ท์์ ์งํํ๋ C++ ํ๋ก์ ํธ ๊ด๋ฆฌ ๊ฐ์์์๋ ์ด๋ฐ ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ๋ง์ด ๋ค๋ฃจ๊ณ ์์ด. ๐
๐ฅ ๊ณ ๊ธ ์ฃผ์
๊ธฐ๋ณธ์ ์ธ ๋ด์ฉ์ ๋ง์คํฐํ๋ค๋ฉด, ์ด์ ๋ ๊ณ ๊ธ ์ฃผ์ ๋ก ๋์ด๊ฐ๋ณด์. ์ด๋ฐ ๊ธฐ๋ฅ๋ค์ ๋๊ท๋ชจ ํ๋ก์ ํธ์์ ํนํ ์ ์ฉํด.
์ฌ์ฉ์ ์ ์ ๋ช ๋ น์ด
๋ฐ๋ณต๋๋ ์์ ์ ํจ์๋ ๋งคํฌ๋ก๋ก ์ ์ํด ์ฌ์ฌ์ฉํ ์ ์์ด:
# ์ฌ์ฉ์ ์ ์ ํจ์
function(add_formatted_target target_name)
add_executable(${target_name} ${ARGN})
target_link_libraries(${target_name} PRIVATE project_options)
# ์ฝ๋ ํฌ๋งทํ
ํ๊ฒ ์ถ๊ฐ
add_custom_target(
format_${target_name}
COMMAND clang-format -i ${ARGN}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "Formatting source files for ${target_name}"
)
endfunction()
# ํจ์ ์ฌ์ฉ
add_formatted_target(my_app src/main.cpp src/utils.cpp)
๋ฏธ๋ฆฌ ์ปดํ์ผ๋ ํค๋(PCH) ์ฌ์ฉ
๋๊ท๋ชจ ํ๋ก์ ํธ์์ ๋น๋ ์๊ฐ์ ๋จ์ถํ๊ธฐ ์ํด PCH๋ฅผ ์ฌ์ฉํ ์ ์์ด:
# PCH ํค๋ ํ์ผ
target_precompile_headers(my_app
PRIVATE
<vector>
<string>
<map>
<memory>
"common/utils.h"
)
์ ๋ํฐ ๋น๋
์ฌ๋ฌ ์์ค ํ์ผ์ ํ๋๋ก ํฉ์ณ์ ์ปดํ์ผ ์๊ฐ์ ๋จ์ถํ ์ ์์ด:
# ์ ๋ํฐ ๋น๋ ํ์ฑํ
set_target_properties(my_app PROPERTIES
UNITY_BUILD ON
UNITY_BUILD_BATCH_SIZE 8 # ํ ๋ฒ์ ํฉ์น ํ์ผ ์
)
์ค์น ๋ฐ ๋ด๋ณด๋ด๊ธฐ
๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋ค๋ฅธ ํ๋ก์ ํธ์์ ์ฌ์ฉํ ์ ์๋๋ก ์ค์น ๊ท์น์ ์ ์ํ ์ ์์ด:
# ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ค์น
install(
TARGETS my_lib
EXPORT MyLibTargets
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
RUNTIME DESTINATION bin
INCLUDES DESTINATION include
)
# ํค๋ ํ์ผ ์ค์น
install(
DIRECTORY include/
DESTINATION include
)
# ํ๊ฒ ๋ด๋ณด๋ด๊ธฐ
install(
EXPORT MyLibTargets
FILE MyLibTargets.cmake
NAMESPACE MyLib::
DESTINATION lib/cmake/MyLib
)
# ์ค์ ํ์ผ ์์ฑ ๋ฐ ์ค์น
configure_package_config_file(
cmake/MyLibConfig.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/MyLibConfig.cmake
INSTALL_DESTINATION lib/cmake/MyLib
)
# ๋ฒ์ ํ์ผ ์์ฑ ๋ฐ ์ค์น
write_basic_package_version_file(
${CMAKE_CURRENT_BINARY_DIR}/MyLibConfigVersion.cmake
VERSION ${PROJECT_VERSION}
COMPATIBILITY SameMajorVersion
)
# ์ค์ ํ์ผ ์ค์น
install(
FILES
${CMAKE_CURRENT_BINARY_DIR}/MyLibConfig.cmake
${CMAKE_CURRENT_BINARY_DIR}/MyLibConfigVersion.cmake
DESTINATION lib/cmake/MyLib
)
์ด๋ฐ ๊ณ ๊ธ ๊ธฐ๋ฅ๋ค์ ๋๊ท๋ชจ ํ๋ก์ ํธ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๊ฐ๋ฐํ ๋ ํนํ ์ ์ฉํด. ๋น๋ ์๊ฐ์ ๋จ์ถํ๊ณ , ๋ค๋ฅธ ํ๋ก์ ํธ์์ ์ฝ๊ฒ ์ฌ์ฉํ ์ ์๋ ํจํค์ง๋ฅผ ๋ง๋ค ์ ์๊ฑฐ๋ . ์ฌ๋ฅ๋ท์์๋ ์ด๋ฐ ๊ณ ๊ธ CMake ๊ธฐ๋ฒ์ ๋ํ ๊ฐ์๊ฐ ์์ด. ์ค๋ฌด์์ ์ ๋ง ๋์์ด ๋ง์ด ๋๋ ๋ด์ฉ์ด์ง! ๐
๐ง ๋ฌธ์ ํด๊ฒฐ
CMake๋ฅผ ์ฌ์ฉํ๋ค ๋ณด๋ฉด ๋ค์ํ ๋ฌธ์ ์ ๋ถ๋ชํ ์ ์์ด. ์์ฃผ ๋ฐ์ํ๋ ๋ฌธ์ ์ ํด๊ฒฐ ๋ฐฉ๋ฒ์ ์์๋ณด์.
์์ฃผ ๋ฐ์ํ๋ ์ค๋ฅ
-
๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฐพ์ง ๋ชปํ๋ ๊ฒฝ์ฐ
CMake๊ฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฐพ์ง ๋ชปํ๋ฉด ๋ค์๊ณผ ๊ฐ์ ์ค๋ฅ๊ฐ ๋ฐ์ํด:
CMake Error at CMakeLists.txt:10 (find_package): Could not find a package configuration file provided by "Boost" with any of the following names: BoostConfig.cmake boost-config.cmakeํด๊ฒฐ ๋ฐฉ๋ฒ:
# ์ถ๊ฐ ๊ฒ์ ๊ฒฝ๋ก ์ง์ set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} "/path/to/boost") # ๋๋ ํ๊ฒฝ ๋ณ์ ์ค์ # export CMAKE_PREFIX_PATH=/path/to/boost:$CMAKE_PREFIX_PATH -
์ปดํ์ผ๋ฌ ํธํ์ฑ ๋ฌธ์
C++ ํ์ค ๋ฒ์ ๋ถ์ผ์น๋ก ์ธํ ์ค๋ฅ:
error: this file requires compiler and library support for the ISO C++ 2017 standardํด๊ฒฐ ๋ฐฉ๋ฒ:
# C++ ํ์ค ๋ฒ์ ๋ช ์์ ์ค์ set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) -
๋น๋ ํ์
๊ด๋ จ ๋ฌธ์
๋ฉํฐ ์ค์ ์์ฑ๊ธฐ(์: Visual Studio)์์ ๋น๋ ํ์ ์ด ์ ์ฉ๋์ง ์๋ ๋ฌธ์ :
ํด๊ฒฐ ๋ฐฉ๋ฒ:
# ๋จ์ผ ์ค์ ์์ฑ๊ธฐ์ฉ if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build type" FORCE) endif() # ๋ฉํฐ ์ค์ ์์ฑ๊ธฐ์ฉ set(CMAKE_CONFIGURATION_TYPES "Debug;Release;RelWithDebInfo;MinSizeRel" CACHE STRING "" FORCE)
๋๋ฒ๊น ํ
CMake ์คํฌ๋ฆฝํธ๋ฅผ ๋๋ฒ๊น ํ๋ ๋ฐฉ๋ฒ:
-
๋ณ์ ๊ฐ ์ถ๋ ฅํ๊ธฐ
message(STATUS "My variable: ${MY_VARIABLE}") # ๋ณ์ ํ์ ํ์ธ if(DEFINED MY_VARIABLE) message(STATUS "MY_VARIABLE is defined") endif() # ๋ฆฌ์คํธ ๋ด์ฉ ์ถ๋ ฅ foreach(item IN LISTS MY_LIST) message(STATUS "List item: ${item}") endforeach() -
--trace ์ต์
์ฌ์ฉํ๊ธฐ
CMake ์คํ ์ --trace ์ต์ ์ ์ฌ์ฉํ๋ฉด ๋ชจ๋ ๋ช ๋ น์ด ์คํ์ ์ถ์ ํ ์ ์์ด:
cmake --trace .. -
--debug-output ์ต์
์ฌ์ฉํ๊ธฐ
๋ ์์ธํ ๋๋ฒ๊ทธ ์ ๋ณด๋ฅผ ๋ณด๋ ค๋ฉด:
cmake --debug-output ..
๋ฌธ์ ํด๊ฒฐ ๋ฅ๋ ฅ์ CMake๋ฅผ ๋ง์คํฐํ๋ ๋ฐ ๋งค์ฐ ์ค์ํด. ์ค๋ฅ ๋ฉ์์ง๋ฅผ ๊ผผ๊ผผํ ์ฝ๊ณ , ๋ฌธ์๋ฅผ ์ฐธ์กฐํ๋ ์ต๊ด์ ๋ค์ด๋ฉด ๋๋ถ๋ถ์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์์ด. ์ฌ๋ฅ๋ท์์๋ CMake ํธ๋ฌ๋ธ์ํ ์ ๊ดํ ์ง๋ฌธ์ด ๋ง์ด ์ฌ๋ผ์ค๋๋ฐ, ์ด๋ฐ ๊ฒฝํ์ ๊ณต์ ํ๋ฉด์ ํจ๊ป ์ฑ์ฅํ ์ ์์ด. ๐
๐ ์ถ๊ฐ ์๋ฃ
CMake์ ๋ํด ๋ ๊น์ด ๊ณต๋ถํ๊ณ ์ถ๋ค๋ฉด ๋ค์ ์๋ฃ๋ค์ ์ฐธ๊ณ ํด๋ณด์:
๐ ์ฑ
- "Professional CMake: A Practical Guide" by Craig Scott
- "CMake Cookbook" by Radovan Bast and Roberto Di Remigio
- "Effective CMake" by Daniel Pfeifer
๐ ์น์ฌ์ดํธ
- CMake ๊ณต์ ๋ฌธ์: https://cmake.org/documentation/
- CMake ํํ ๋ฆฌ์ผ: https://cmake.org/cmake/help/latest/guide/tutorial/
- Modern CMake: https://cliutils.gitlab.io/modern-cmake/
๐ฌ ๋์์
- CppCon์ "More Modern CMake" ๊ฐ์ฐ
- ์ฌ๋ฅ๋ท์ "C++ ๋น๋ ์์คํ ๋ง์คํฐํ๊ธฐ" ๊ฐ์
- YouTube์ "CMake Tutorial" ์๋ฆฌ์ฆ
์ด๋ฐ ์๋ฃ๋ค์ ํตํด CMake์ ๋ํ ์ดํด๋ฅผ ๋ ๊น๊ฒ ํ ์ ์์ด. ํนํ ์ฌ๋ฅ๋ท์์ ์ ๊ณตํ๋ ์ค๋ฌด ์ค์ฌ์ CMake ๊ฐ์๋ ์ค์ ํ๋ก์ ํธ์ ๋ฐ๋ก ์ ์ฉํ ์ ์๋ ๋ด์ฉ์ด ๋ง์์ ์ถ์ฒํด! ๐
๐ ๋ง์น๋ฉฐ
์ง๊ธ๊น์ง CMake์ ๊ธฐ๋ณธ๋ถํฐ ๊ณ ๊ธ ์ฃผ์ ๊น์ง ๋ค์ํ ๋ด์ฉ์ ์ดํด๋ดค์ด. CMake๋ ์ฒ์์๋ ๋ฐฐ์ฐ๊ธฐ ์ด๋ ค์ธ ์ ์์ง๋ง, ํ๋ฒ ์ต์ํด์ง๋ฉด C++ ํ๋ก์ ํธ ๊ด๋ฆฌ์ ์ ๋ง ๊ฐ๋ ฅํ ๋๊ตฌ๊ฐ ๋ผ. ํนํ ํฌ๋ก์ค ํ๋ซํผ ๊ฐ๋ฐ์ด๋ ๋๊ท๋ชจ ํ๋ก์ ํธ์์๋ ํ์์ ์ธ ๋๊ตฌ๋ผ๊ณ ํ ์ ์์ง.
CMake๋ฅผ ๋ง์คํฐํ๋ ๊ฒ์ ํ๋ฃจ์์นจ์ ์ด๋ฃจ์ด์ง์ง ์์. ๊พธ์คํ ํ์ต๊ณผ ์ค์ต์ด ํ์ํด. ์์ ํ๋ก์ ํธ๋ถํฐ ์์ํด์ ์ ์ ๋ณต์กํ ๊ธฐ๋ฅ์ ์ถ๊ฐํด๋๊ฐ๋ ๊ฒ์ด ์ข์ ๋ฐฉ๋ฒ์ด์ผ. ๊ทธ๋ฆฌ๊ณ ๋ค๋ฅธ ์คํ ์์ค ํ๋ก์ ํธ์ CMakeLists.txt ํ์ผ์ ๋ถ์ํด๋ณด๋ ๊ฒ๋ ๋ง์ ๋์์ด ๋ผ. ๐
์ฌ๋ฅ๋ท์์๋ ์ด๋ฐ CMake ๊ด๋ จ ๊ฐ์์ ํ๋ก์ ํธ ๊ฒฝํ์ ๊ณต์ ํ ์ ์๋ ๊ธฐํ๊ฐ ๋ง์. ํนํ C++ ๊ฐ๋ฐ์๋ค ์ฌ์ด์์๋ ๋น๋ ์์คํ ๊ตฌ์ฑ ๊ฒฝํ์ด ๋งค์ฐ ๊ฐ์น ์๊ฒ ํ๊ฐ๋๊ฑฐ๋ . ์ฌ๋ฌ๋ถ๋ ์ด ๊ธ์ ํตํด CMake์ ๋ํ ๊ธฐ๋ณธ์ ์ธ ์ดํด๋ฅผ ์ป๊ณ , ๋ ๋์๊ฐ ์ค์ ํ๋ก์ ํธ์ ์ ์ฉํด๋ณด๊ธธ ๋ฐ๋ผ! ๐
์ง๋ฌธ์ด๋ ๋ ์๊ณ ์ถ์ ๋ด์ฉ์ด ์๋ค๋ฉด ์ฌ๋ฅ๋ท ์ปค๋ฎค๋ํฐ์์ ์ธ์ ๋ ์ง ๋ฌผ์ด๋ด. ํจ๊ป ์ฑ์ฅํ๋ ๊ฐ๋ฐ์ ์ปค๋ฎค๋ํฐ์์ ๋ง๋์! ๐
๊ด๋ จ ํค์๋
๋๊ธ ์์ฑ
์ด ๊ธ์ ๋ํ ์ฌ๋ฌ๋ถ์ ์๊ฐ์ ๋ค๋ ค์ฃผ์ธ์
๋ก๊ทธ์ธ์ด ํ์ํฉ๋๋ค
๋๊ธ์ ์์ฑํ๋ ค๋ฉด ๋จผ์ ๋ก๊ทธ์ธํด์ฃผ์ธ์.
๋๊ธ 0
์ง์์ธ์ ์ฒ - ์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
- ์ ์๊ถ ๋ฐ ์์ ๊ถ: ๋ณธ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ๋ ์ AI ๊ธฐ์ ๋ก ์์ฑ๋์์ผ๋ฉฐ, ๋ํ๋ฏผ๊ตญ ์ ์๊ถ๋ฒ ๋ฐ ๊ตญ์ ์ ์๊ถ ํ์ฝ์ ์ํด ๋ณดํธ๋ฉ๋๋ค.
- AI ์์ฑ ์ปจํ ์ธ ์ ๋ฒ์ ์ง์: ๋ณธ AI ์์ฑ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ์ง์ ์ฐฝ์๋ฌผ๋ก ์ธ์ ๋๋ฉฐ, ๊ด๋ จ ๋ฒ๊ท์ ๋ฐ๋ผ ์ ์๊ถ ๋ณดํธ๋ฅผ ๋ฐ์ต๋๋ค.
- ์ฌ์ฉ ์ ํ: ์ฌ๋ฅ๋ท์ ๋ช ์์ ์๋ฉด ๋์ ์์ด ๋ณธ ์ปจํ ์ธ ๋ฅผ ๋ณต์ , ์์ , ๋ฐฐํฌ, ๋๋ ์์ ์ ์ผ๋ก ํ์ฉํ๋ ํ์๋ ์๊ฒฉํ ๊ธ์ง๋ฉ๋๋ค.
- ๋ฐ์ดํฐ ์์ง ๊ธ์ง: ๋ณธ ์ปจํ ์ธ ์ ๋ํ ๋ฌด๋จ ์คํฌ๋ํ, ํฌ๋กค๋ง, ๋ฐ ์๋ํ๋ ๋ฐ์ดํฐ ์์ง์ ๋ฒ์ ์ ์ฌ์ ๋์์ด ๋ฉ๋๋ค.
- AI ํ์ต ์ ํ: ์ฌ๋ฅ๋ท์ AI ์์ฑ ์ปจํ ์ธ ๋ฅผ ํ AI ๋ชจ๋ธ ํ์ต์ ๋ฌด๋จ ์ฌ์ฉํ๋ ํ์๋ ๊ธ์ง๋๋ฉฐ, ์ด๋ ์ง์ ์ฌ์ฐ๊ถ ์นจํด๋ก ๊ฐ์ฃผ๋ฉ๋๋ค.
์์ง ๋๊ธ์ด ์์ต๋๋ค.