์ฝ˜ํ…์ธ  ๋Œ€ํ‘œ ์ด๋ฏธ์ง€ - ๐Ÿ› ๏ธ ๋นŒ๋“œ ์‹œ์Šคํ…œ: CMake ์‚ฌ์šฉ๋ฒ• ๋งˆ์Šคํ„ฐํ•˜๊ธฐ ๐Ÿ› ๏ธ

๐Ÿ› ๏ธ ๋นŒ๋“œ ์‹œ์Šคํ…œ: CMake ์‚ฌ์šฉ๋ฒ• ๋งˆ์Šคํ„ฐํ•˜๊ธฐ ๐Ÿ› ๏ธ

C++ ํ”„๋กœ์ ํŠธ๋ฅผ ์œ„ํ•œ ํ˜„๋Œ€์  ๋นŒ๋“œ ์‹œ์Šคํ…œ ๊ฐ€์ด๋“œ

์•ˆ๋…•? ์˜ค๋Š˜์€ C++ ๊ฐœ๋ฐœ์ž๋ผ๋ฉด ๊ผญ ์•Œ์•„์•ผ ํ•  CMake์— ๋Œ€ํ•ด ํ•จ๊ป˜ ์•Œ์•„๋ณด์ž! ํ”„๋กœ์ ํŠธ๊ฐ€ ์ปค์งˆ์ˆ˜๋ก ์†Œ์Šค ํŒŒ์ผ ๊ด€๋ฆฌ์™€ ๋นŒ๋“œ ๊ณผ์ •์ด ๋ณต์žกํ•ด์ง€๋Š” ๊ฑด ๋‹น์—ฐํ•œ ์ผ์ด์ง€. ๊ทธ๋Ÿด ๋•Œ CMake ๊ฐ™์€ ๋นŒ๋“œ ์‹œ์Šคํ…œ์ด ์šฐ๋ฆฌ์˜ ๊ตฌ์›์ž๊ฐ€ ๋˜์–ด์ค„ ๊ฑฐ์•ผ. ๐Ÿ˜Ž

๋‚ด๊ฐ€ ์žฌ๋Šฅ๋„ท์—์„œ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ฐ•์˜๋ฅผ ์ง„ํ–‰ํ•˜๋ฉด์„œ ๊ฐ€์žฅ ๋งŽ์ด ๋ฐ›๋Š” ์งˆ๋ฌธ ์ค‘ ํ•˜๋‚˜๊ฐ€ ๋ฐ”๋กœ "๋นŒ๋“œ ์‹œ์Šคํ…œ์€ ์–ด๋–ป๊ฒŒ ๊ตฌ์„ฑํ•˜๋‚˜์š”?"์•ผ. ํŠนํžˆ C++ ํ”„๋กœ์ ํŠธ์—์„œ ์ด ๋ถ€๋ถ„์€ ์ •๋ง ์ค‘์š”ํ•˜๊ฑฐ๋“ . ์˜ค๋Š˜ ์ด ๊ธ€์„ ํ†ตํ•ด ๊ทธ ํ•ด๋‹ต์„ ์ฐพ์•„๋ณด์ž!

๐Ÿค” ์™œ CMake๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ• ๊นŒ?

C++ ํ”„๋กœ์ ํŠธ๋ฅผ ๊ฐœ๋ฐœํ•  ๋•Œ ๊ทธ๋ƒฅ IDE์˜ '๋นŒ๋“œ' ๋ฒ„ํŠผ๋งŒ ๋ˆ„๋ฅด๋ฉด ๋˜๋Š” ๊ฑฐ ์•„๋‹ˆ๋ƒ๊ณ ? ์Œ... ์ž‘์€ ํ”„๋กœ์ ํŠธ๋ผ๋ฉด ๊ทธ๋ž˜๋„ ๊ดœ์ฐฎ์„ ์ˆ˜ ์žˆ์–ด. ํ•˜์ง€๋งŒ ํ”„๋กœ์ ํŠธ๊ฐ€ ์ปค์ง€๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฌธ์ œ๋“ค์ด ์ƒ๊ฒจ:

  1. ์—ฌ๋Ÿฌ ํ”Œ๋žซํผ(Windows, Linux, macOS)์—์„œ ๋™์ž‘ํ•ด์•ผ ํ•  ๋•Œ
  2. ๋‹ค์–‘ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์˜์กด์„ฑ์„ ๊ด€๋ฆฌํ•ด์•ผ ํ•  ๋•Œ
  3. ํŒ€ ๋‹จ์œ„๋กœ ๊ฐœ๋ฐœํ•  ๋•Œ ๋ชจ๋“  ๊ฐœ๋ฐœ์ž๊ฐ€ ๋™์ผํ•œ ํ™˜๊ฒฝ์—์„œ ๋นŒ๋“œํ•ด์•ผ ํ•  ๋•Œ
  4. CI/CD ํŒŒ์ดํ”„๋ผ์ธ์„ ๊ตฌ์ถ•ํ•  ๋•Œ
  5. ๋นŒ๋“œ ์˜ต์…˜์„ ์„ธ๋ฐ€ํ•˜๊ฒŒ ์ œ์–ดํ•ด์•ผ ํ•  ๋•Œ

CMake๋Š” ์ด๋Ÿฐ ๋ฌธ์ œ๋“ค์„ ํ•ด๊ฒฐํ•ด์ฃผ๋Š” ํฌ๋กœ์Šค ํ”Œ๋žซํผ ๋นŒ๋“œ ์‹œ์Šคํ…œ ์ƒ์„ฑ๊ธฐ์•ผ. ํ•œ ๋ฒˆ CMake ์„ค์ • ํŒŒ์ผ์„ ์ž‘์„ฑํ•˜๋ฉด, ์–ด๋–ค ํ”Œ๋žซํผ์—์„œ๋“  ํ•„์š”ํ•œ ๋นŒ๋“œ ํŒŒ์ผ(Makefile, Visual Studio ํ”„๋กœ์ ํŠธ ๋“ฑ)์„ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•ด์ค˜. ์ •๋ง ํŽธ๋ฆฌํ•˜์ง€? ๐Ÿš€

๐Ÿ“š CMake ๊ฐœ์š”

CMakeLists.txt CMake ์‹คํ–‰ ๋นŒ๋“œ ํŒŒ์ผ ์ƒ์„ฑ Makefile VS ํ”„๋กœ์ ํŠธ Xcode ํ”„๋กœ์ ํŠธ CMake ์ž‘๋™ ์›๋ฆฌ

CMake๋Š” 1999๋…„์— ์ฒ˜์Œ ๋“ฑ์žฅํ–ˆ์–ด. ์ฒ˜์Œ์—๋Š” ๋‹จ์ˆœํ•œ ๋นŒ๋“œ ๋„๊ตฌ์˜€์ง€๋งŒ, ์ง€๊ธˆ์€ C++๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๋‹ค์–‘ํ•œ ์–ธ์–ด์˜ ํ”„๋กœ์ ํŠธ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๊ฐ•๋ ฅํ•œ ๋„๊ตฌ๋กœ ๋ฐœ์ „ํ–ˆ์ง€. ํŠนํžˆ C++ ํ‘œ์ค€์ด ๊ณ„์† ๋ฐœ์ „ํ•˜๋ฉด์„œ CMake๋„ ํ•จ๊ป˜ ์ง„ํ™”ํ•ด์™”์–ด. ํ˜„์žฌ๋Š” ๋ฒ„์ „ 3.x๋Œ€๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๊ณ , ์ตœ์‹  C++ ํ‘œ์ค€๊ณผ ๋‹ค์–‘ํ•œ ๋นŒ๋“œ ํ™˜๊ฒฝ์„ ์™„๋ฒฝํ•˜๊ฒŒ ์ง€์›ํ•ด.

CMake์˜ ํ•ต์‹ฌ ๊ฐœ๋…์€ ๋‹ค์Œ๊ณผ ๊ฐ™์•„:

  1. CMakeLists.txt: ํ”„๋กœ์ ํŠธ ๊ตฌ์„ฑ์„ ์ •์˜ํ•˜๋Š” ํ•ต์‹ฌ ํŒŒ์ผ
  2. ํƒ€๊ฒŸ(Target): ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋‚˜ ์‹คํ–‰ ํŒŒ์ผ๊ณผ ๊ฐ™์€ ๋นŒ๋“œ ๊ฒฐ๊ณผ๋ฌผ
  3. ๋ณ€์ˆ˜(Variable): CMake ๋‚ด์—์„œ ์ •๋ณด๋ฅผ ์ €์žฅํ•˜๊ณ  ์ฐธ์กฐํ•˜๋Š” ๋ฐฉ๋ฒ•
  4. ๋ช…๋ น์–ด(Command): CMake ์Šคํฌ๋ฆฝํŠธ์—์„œ ์‚ฌ์šฉํ•˜๋Š” ํ•จ์ˆ˜๋“ค
  5. ๋ชจ๋“ˆ(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)

๊ฐ ์ค„์ด ๋ฌด์Šจ ์˜๋ฏธ์ธ์ง€ ์‚ดํŽด๋ณด์ž:

  1. cmake_minimum_required: ํ•„์š”ํ•œ ์ตœ์†Œ CMake ๋ฒ„์ „์„ ์ง€์ •ํ•ด
  2. project: ํ”„๋กœ์ ํŠธ ์ด๋ฆ„๊ณผ ๋ฒ„์ „์„ ์„ค์ •ํ•ด
  3. set(CMAKE_CXX_STANDARD 17): C++17 ํ‘œ์ค€์„ ์‚ฌ์šฉํ•˜๋„๋ก ์„ค์ •ํ•ด
  4. 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 ๋ช…๋ น์–ด add_executable ์‹คํ–‰ ํŒŒ์ผ ํƒ€๊ฒŸ์„ ์ƒ์„ฑ add_executable(target_name source1.cpp source2.cpp) add_library ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํƒ€๊ฒŸ์„ ์ƒ์„ฑ add_library(lib_name STATIC|SHARED source1.cpp source2.cpp) target_link_libraries ํƒ€๊ฒŸ์— ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋งํฌ target_link_libraries(target_name PRIVATE|PUBLIC|INTERFACE lib) target_include_directories ํ—ค๋” ํŒŒ์ผ ๊ฒฝ๋กœ ์ง€์ • target_include_directories(target PRIVATE|PUBLIC|INTERFACE dir) find_package ์™ธ๋ถ€ ํŒจํ‚ค์ง€/๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ฐพ๊ธฐ find_package(Package 1.0 REQUIRED|OPTIONAL) set ๋ณ€์ˆ˜ ์„ค์ • set(VARIABLE_NAME value [CACHE TYPE DOCSTRING])

์ด ์™ธ์—๋„ ๋งŽ์€ ๋ช…๋ น์–ด๊ฐ€ ์žˆ์ง€๋งŒ, ์œ„์˜ ๋ช…๋ น์–ด๋“ค๋งŒ ์•Œ์•„๋„ ๊ธฐ๋ณธ์ ์ธ 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)

์ด ๋ฐฉ์‹์˜ ์žฅ์ ์€:

  1. ์˜์กด์„ฑ์ด ๋ช…ํ™•ํ•ด์ง
  2. ์†์„ฑ์˜ ๋ฒ”์œ„(PRIVATE, PUBLIC, INTERFACE)๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Œ
  3. ๋ถˆํ•„์š”ํ•œ ์ „์—ญ ์ƒํƒœ๋ฅผ ํ”ผํ•  ์ˆ˜ ์žˆ์Œ

์ธํ„ฐํŽ˜์ด์Šค ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

ํ˜„๋Œ€์ ์ธ 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 ๋ชจ๋ฒ” ์‚ฌ๋ก€ 1 ํƒ€๊ฒŸ ์ค‘์‹ฌ ์ ‘๊ทผ๋ฒ• ์‚ฌ์šฉํ•˜๊ธฐ ์ „์—ญ ๋ณ€์ˆ˜ ๋Œ€์‹  target_* ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•ด ๊ฐ ํƒ€๊ฒŸ์— ์ง์ ‘ ์†์„ฑ ์„ค์ • 2 ๋ฒ”์œ„ ์ง€์ •์ž ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์‚ฌ์šฉํ•˜๊ธฐ PRIVATE, PUBLIC, INTERFACE ๋ฒ”์œ„๋ฅผ ๋ช…ํ™•ํ•˜๊ฒŒ ๊ตฌ๋ถ„ํ•ด ์‚ฌ์šฉ 3 ๋ณ€์ˆ˜ ์ด๋ฆ„ ๊ทœ์น™ ์ง€ํ‚ค๊ธฐ ํ”„๋กœ์ ํŠธ ์ ‘๋‘์‚ฌ๋ฅผ ์‚ฌ์šฉํ•ด ๋ณ€์ˆ˜ ์ด๋ฆ„ ์ถฉ๋Œ ๋ฐฉ์ง€ 4 ์˜ต์…˜ ์ œ๊ณตํ•˜๊ธฐ option() ๋ช…๋ น์–ด๋กœ ์‚ฌ์šฉ์ž๊ฐ€ ๋นŒ๋“œ๋ฅผ ์ปค์Šคํ„ฐ๋งˆ์ด์ฆˆํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•จ 5 ๋‚ด๋ถ€ ๋ณ€์ˆ˜ ์บ์‹ฑ ํ”ผํ•˜๊ธฐ ๋ถˆํ•„์š”ํ•œ CACHE ๋ณ€์ˆ˜ ์‚ฌ์šฉ์„ ํ”ผํ•˜๊ณ  ๋กœ์ปฌ ๋ณ€์ˆ˜ ํ™œ์šฉ 6 find_package ํ™œ์šฉํ•˜๊ธฐ ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ์ง์ ‘ ๊ฒฝ๋กœ ์ง€์ •๋ณด๋‹ค find_package ์‚ฌ์šฉ 7 ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐํ™”ํ•˜๊ธฐ add_subdirectory๋กœ ๋…ผ๋ฆฌ์ ์ธ ํ•˜์œ„ ํ”„๋กœ์ ํŠธ ๊ตฌ์„ฑ 8 ๋ฒ„์ „ ์š”๊ตฌ์‚ฌํ•ญ ๋ช…์‹œํ•˜๊ธฐ cmake_minimum_required๋กœ ํ•„์š”ํ•œ ์ตœ์†Œ CMake ๋ฒ„์ „ ์ง€์ • 9 ์„ค์น˜ ๊ทœ์น™ ์ œ๊ณตํ•˜๊ธฐ install() ๋ช…๋ น์–ด๋กœ ํ”„๋กœ์ ํŠธ ์„ค์น˜ ๋ฐฉ๋ฒ• ์ •์˜ 10 ๋ฌธ์„œํ™”ํ•˜๊ธฐ ์ฃผ์„๊ณผ README๋กœ ๋นŒ๋“œ ๋ฐฉ๋ฒ•๊ณผ ์˜ต์…˜ ์„ค๋ช…

์ด๋Ÿฐ ๋ชจ๋ฒ” ์‚ฌ๋ก€๋ฅผ ๋”ฐ๋ฅด๋ฉด 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๋ฅผ ์‚ฌ์šฉํ•˜๋‹ค ๋ณด๋ฉด ๋‹ค์–‘ํ•œ ๋ฌธ์ œ์— ๋ถ€๋”ชํž ์ˆ˜ ์žˆ์–ด. ์ž์ฃผ ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ์™€ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ณด์ž.

์ž์ฃผ ๋ฐœ์ƒํ•˜๋Š” ์˜ค๋ฅ˜

  1. ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ฐพ์ง€ ๋ชปํ•˜๋Š” ๊ฒฝ์šฐ

    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
  2. ์ปดํŒŒ์ผ๋Ÿฌ ํ˜ธํ™˜์„ฑ ๋ฌธ์ œ

    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)
  3. ๋นŒ๋“œ ํƒ€์ž… ๊ด€๋ จ ๋ฌธ์ œ

    ๋ฉ€ํ‹ฐ ์„ค์ • ์ƒ์„ฑ๊ธฐ(์˜ˆ: 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 ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋””๋ฒ„๊น…ํ•˜๋Š” ๋ฐฉ๋ฒ•:

  1. ๋ณ€์ˆ˜ ๊ฐ’ ์ถœ๋ ฅํ•˜๊ธฐ
    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()
  2. --trace ์˜ต์…˜ ์‚ฌ์šฉํ•˜๊ธฐ

    CMake ์‹คํ–‰ ์‹œ --trace ์˜ต์…˜์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ชจ๋“  ๋ช…๋ น์–ด ์‹คํ–‰์„ ์ถ”์ ํ•  ์ˆ˜ ์žˆ์–ด:

    cmake --trace ..
  3. --debug-output ์˜ต์…˜ ์‚ฌ์šฉํ•˜๊ธฐ

    ๋” ์ž์„ธํ•œ ๋””๋ฒ„๊ทธ ์ •๋ณด๋ฅผ ๋ณด๋ ค๋ฉด:

    cmake --debug-output ..

๋ฌธ์ œ ํ•ด๊ฒฐ ๋Šฅ๋ ฅ์€ CMake๋ฅผ ๋งˆ์Šคํ„ฐํ•˜๋Š” ๋ฐ ๋งค์šฐ ์ค‘์š”ํ•ด. ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€๋ฅผ ๊ผผ๊ผผํžˆ ์ฝ๊ณ , ๋ฌธ์„œ๋ฅผ ์ฐธ์กฐํ•˜๋Š” ์Šต๊ด€์„ ๋“ค์ด๋ฉด ๋Œ€๋ถ€๋ถ„์˜ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์–ด. ์žฌ๋Šฅ๋„ท์—์„œ๋„ CMake ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ…์— ๊ด€ํ•œ ์งˆ๋ฌธ์ด ๋งŽ์ด ์˜ฌ๋ผ์˜ค๋Š”๋ฐ, ์ด๋Ÿฐ ๊ฒฝํ—˜์„ ๊ณต์œ ํ•˜๋ฉด์„œ ํ•จ๊ป˜ ์„ฑ์žฅํ•  ์ˆ˜ ์žˆ์–ด. ๐Ÿ”

๐Ÿ“š ์ถ”๊ฐ€ ์ž๋ฃŒ

CMake์— ๋Œ€ํ•ด ๋” ๊นŠ์ด ๊ณต๋ถ€ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ๋‹ค์Œ ์ž๋ฃŒ๋“ค์„ ์ฐธ๊ณ ํ•ด๋ณด์ž:

๐Ÿ“– ์ฑ…

  1. "Professional CMake: A Practical Guide" by Craig Scott
  2. "CMake Cookbook" by Radovan Bast and Roberto Di Remigio
  3. "Effective CMake" by Daniel Pfeifer

๐ŸŒ ์›น์‚ฌ์ดํŠธ

  1. CMake ๊ณต์‹ ๋ฌธ์„œ: https://cmake.org/documentation/
  2. CMake ํŠœํ† ๋ฆฌ์–ผ: https://cmake.org/cmake/help/latest/guide/tutorial/
  3. Modern CMake: https://cliutils.gitlab.io/modern-cmake/

๐ŸŽฌ ๋™์˜์ƒ

  1. CppCon์˜ "More Modern CMake" ๊ฐ•์—ฐ
  2. ์žฌ๋Šฅ๋„ท์˜ "C++ ๋นŒ๋“œ ์‹œ์Šคํ…œ ๋งˆ์Šคํ„ฐํ•˜๊ธฐ" ๊ฐ•์˜
  3. YouTube์˜ "CMake Tutorial" ์‹œ๋ฆฌ์ฆˆ

์ด๋Ÿฐ ์ž๋ฃŒ๋“ค์„ ํ†ตํ•ด CMake์— ๋Œ€ํ•œ ์ดํ•ด๋ฅผ ๋” ๊นŠ๊ฒŒ ํ•  ์ˆ˜ ์žˆ์–ด. ํŠนํžˆ ์žฌ๋Šฅ๋„ท์—์„œ ์ œ๊ณตํ•˜๋Š” ์‹ค๋ฌด ์ค‘์‹ฌ์˜ CMake ๊ฐ•์˜๋Š” ์‹ค์ œ ํ”„๋กœ์ ํŠธ์— ๋ฐ”๋กœ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋‚ด์šฉ์ด ๋งŽ์•„์„œ ์ถ”์ฒœํ•ด! ๐ŸŒŸ

๐Ÿ ๋งˆ์น˜๋ฉฐ

์ง€๊ธˆ๊นŒ์ง€ CMake์˜ ๊ธฐ๋ณธ๋ถ€ํ„ฐ ๊ณ ๊ธ‰ ์ฃผ์ œ๊นŒ์ง€ ๋‹ค์–‘ํ•œ ๋‚ด์šฉ์„ ์‚ดํŽด๋ดค์–ด. CMake๋Š” ์ฒ˜์Œ์—๋Š” ๋ฐฐ์šฐ๊ธฐ ์–ด๋ ค์šธ ์ˆ˜ ์žˆ์ง€๋งŒ, ํ•œ๋ฒˆ ์ต์ˆ™ํ•ด์ง€๋ฉด C++ ํ”„๋กœ์ ํŠธ ๊ด€๋ฆฌ์— ์ •๋ง ๊ฐ•๋ ฅํ•œ ๋„๊ตฌ๊ฐ€ ๋ผ. ํŠนํžˆ ํฌ๋กœ์Šค ํ”Œ๋žซํผ ๊ฐœ๋ฐœ์ด๋‚˜ ๋Œ€๊ทœ๋ชจ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ํ•„์ˆ˜์ ์ธ ๋„๊ตฌ๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ์ง€.

CMake๋ฅผ ๋งˆ์Šคํ„ฐํ•˜๋Š” ๊ฒƒ์€ ํ•˜๋ฃจ์•„์นจ์— ์ด๋ฃจ์–ด์ง€์ง€ ์•Š์•„. ๊พธ์ค€ํ•œ ํ•™์Šต๊ณผ ์‹ค์Šต์ด ํ•„์š”ํ•ด. ์ž‘์€ ํ”„๋กœ์ ํŠธ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•ด์„œ ์ ์  ๋ณต์žกํ•œ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•ด๋‚˜๊ฐ€๋Š” ๊ฒƒ์ด ์ข‹์€ ๋ฐฉ๋ฒ•์ด์•ผ. ๊ทธ๋ฆฌ๊ณ  ๋‹ค๋ฅธ ์˜คํ”ˆ ์†Œ์Šค ํ”„๋กœ์ ํŠธ์˜ CMakeLists.txt ํŒŒ์ผ์„ ๋ถ„์„ํ•ด๋ณด๋Š” ๊ฒƒ๋„ ๋งŽ์€ ๋„์›€์ด ๋ผ. ๐Ÿ”

์žฌ๋Šฅ๋„ท์—์„œ๋Š” ์ด๋Ÿฐ CMake ๊ด€๋ จ ๊ฐ•์˜์™€ ํ”„๋กœ์ ํŠธ ๊ฒฝํ—˜์„ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐํšŒ๊ฐ€ ๋งŽ์•„. ํŠนํžˆ C++ ๊ฐœ๋ฐœ์ž๋“ค ์‚ฌ์ด์—์„œ๋Š” ๋นŒ๋“œ ์‹œ์Šคํ…œ ๊ตฌ์„ฑ ๊ฒฝํ—˜์ด ๋งค์šฐ ๊ฐ€์น˜ ์žˆ๊ฒŒ ํ‰๊ฐ€๋˜๊ฑฐ๋“ . ์—ฌ๋Ÿฌ๋ถ„๋„ ์ด ๊ธ€์„ ํ†ตํ•ด CMake์— ๋Œ€ํ•œ ๊ธฐ๋ณธ์ ์ธ ์ดํ•ด๋ฅผ ์–ป๊ณ , ๋” ๋‚˜์•„๊ฐ€ ์‹ค์ œ ํ”„๋กœ์ ํŠธ์— ์ ์šฉํ•ด๋ณด๊ธธ ๋ฐ”๋ผ! ๐Ÿš€

์งˆ๋ฌธ์ด๋‚˜ ๋” ์•Œ๊ณ  ์‹ถ์€ ๋‚ด์šฉ์ด ์žˆ๋‹ค๋ฉด ์žฌ๋Šฅ๋„ท ์ปค๋ฎค๋‹ˆํ‹ฐ์—์„œ ์–ธ์ œ๋“ ์ง€ ๋ฌผ์–ด๋ด. ํ•จ๊ป˜ ์„ฑ์žฅํ•˜๋Š” ๊ฐœ๋ฐœ์ž ์ปค๋ฎค๋‹ˆํ‹ฐ์—์„œ ๋งŒ๋‚˜์ž! ๐Ÿ‘‹

๋Œ“๊ธ€ ์ž‘์„ฑ

์ด ๊ธ€์— ๋Œ€ํ•œ ์—ฌ๋Ÿฌ๋ถ„์˜ ์ƒ๊ฐ์„ ๋“ค๋ ค์ฃผ์„ธ์š”

๋Œ“๊ธ€ 0
๋Œ“๊ธ€์„ ๋ถˆ๋Ÿฌ์˜ค๋Š” ์ค‘์ž…๋‹ˆ๋‹ค.

์•„์ง ๋Œ“๊ธ€์ด ์—†์Šต๋‹ˆ๋‹ค.