๐ก ๋ณธ ๋ฌธ์๋ 'An Introduction to Modern CMake'์ ๋ํด ์ ๋ฆฌํด๋์ ๊ธ์ ๋๋ค.
CMake๋ฅผ ์ฌ์ฉํ๋ ์ด์ ๋ถํฐ CMake์ ๊ตฌ์ฑ ๋ฐ CMakeLists.txt ํ์ผ ์์ฑ๋ฒ๊น์ง ๋ค๋ฃจ๊ณ ์์ผ๋ CMake๋ฅผ ์ ๋ฌธํ์ฌ ํ์ฉํ๋ ์ ์ฅ์์ ๋ง์ ๋์์ด ๋ ๊ฒ์ ๋๋ค.
1. CMake ๋
1.1 CMake ๋์
CMake๋ Kitware์์ ๊ฐ๋ฐํ๊ณ ์์ผ๋ฉฐ, cmake.org์์ ํ์ตํ๊ณ ๋ค์ด๋ก๋ ํ ์ ์์ต๋๋ค.
์ ํต์ ์ธ C/C++ ๋น๋ ๋๊ตฌ๋ make์ ๋๋ค. make๋ Makefile์ ์์ฑํด ์ฃผ์ด์ผ ํ๋๋ฐ, Makefile ์์ฑ์ ์์กด๊ด๊ณ๋ฅผ ๊ฐ๋ฐ์๊ฐ ์ง์ ๊ธฐ์ ํด์ผ ํ๋ฉฐ, ๊ฐ๋ฐ์๋ ์ ํํ ์์กด์ฑ์ ์ํด ์์ค์ฝ๋๋ฅผ ๋ค์ฌ๋ค๋ณด๋ฉฐ ๋ง์ ๋ ธ๋์ ํฌ์ ํ์ฌ ์์ฑํด์ผ ํฉ๋๋ค.
Makefile ์์ฑ์ ์ค์๋ก ์์กด๊ด๊ณ๋ฅผ ๋น ๋จ๋ฆฌ๋ฉด ๋ณ๊ฒฝ์ด ์ ๋ฐ์ดํธ ๋์ง ์๊ฑฐ๋, ์ปดํ์ผ ์ค๋ฅ๋ ๋ฐํ์ ์ค๋ฅ๊ฐ ๋ฐ์ํ๊ธฐ๋ ํฉ๋๋ค. ํนํ ๋ฐํ์ ์ค๋ฅ๋ ๊ทธ ์์ธ์ ํ์ ํ๊ธฐ๋ ์ด๋ ต์ต๋๋ค. make ์ฌ์ฉ์ clean ๊ตฌ์ฑ์ ์์ฃผ ์ฌ์ฉํ๊ธฐ๋ ํ๋ ์ด์ ๊ธฐ๋ ํฉ๋๋ค.
CMake๋ ์์คํ์ผ์ ํ์ฑํ์ฌ ์์กด๊ด๊ณ๋ฅผ ํ์ ํ์ฌ ์๋์ผ๋ก Makefile๋ค์ด ์์ฑ๋๋๋ก ๋๋ ๊ฒ์ด 1์ฐจ ๋ชฉํ ์ ๋๋ค.
1.2 CMake ๋จ๊ณ
CMake๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ cmake์ ์ํด CMakeLists.txt๋ฅผ ํ์ฑํ๊ฑฐ๋ Makefile๋ค์ ์์ฑํ๋ ๊ตฌ์ฑ(Configure) ๋จ๊ณ์, make์ ์ํ ๋น๋ (Build) ๋จ๊ณ + ์ค์น(install) ๋จ๊ณ๋ก ๋๋ ๋ณผ ์ ์์ต๋๋ค.
Configure ๋จ๊ณ: CMakeLists.txt๋ฅผ ํ์ฑํ๊ณ ์คํํ์ฌ Makefile ์ด๋ Ninja, vsproj๋ฑ์ ์์ฑํ๋ ๋จ๊ณ์ด๋ฉฐ, ์ด ํ์ผ๋ค์ ์๋์ผ๋ก ๊ตฌ์ฑํ๋ ๊ฒ์ด cmake์ ๊ธฐ๋ณธ ๋ชฉํ ์ ๋๋ค. ์ด ๊ธ์ Makefile๋ง์ ๊ตฌ์ฑํ๋ ๊ณผ์ ์ ๋ค๋ฃน๋๋ค.
- cmake ..: CMakeLists.txt -> Cmake๋ฅผ ์ด์ฉํ์ฌ Makefile ์์ฑ
build ๋จ๊ณ: ๋ค๋ฅธ ์ธ๋ถ ๋๊ตฌ๋ฅผ ์ฌ์ฉํฉ๋๋ค. Makefile์ ์์ฑํ์์ผ๋ฉด make๋ฅผ ์คํ ํฉ๋๋ค.
- make: Makefile์ ์ด์ฉํ์ฌ ์คํ ํ์ผ ์์ฑ.
install ๋จ๊ณ:
- sudo make install:
+ ๋น๋ ์ต์ (CMAKE_BUILD_TYPE)
๋ค์ํ ๋ชจ๋์ ๋น๋์ต์ ์ผ๋ก ์คํํ ์ ์์ต๋๋ค. ์ ํํ ๋น๋์ต์ ์ ๋ฐ๋ผ ์ปดํ์ผ ๋ฐ ๋งํฌ ์ต์ ์ด ์ถ๊ฐ ๋ฉ๋๋ค.
- Debug(`-O0 -g`): ๋๋ฒ๊น
์ ์ํ ๋น๋.
- No optimization, asserts enabled, [custom debug (output) code enabled], debug info included in executable (so you can step through the code with a debugger and have address to source-file:line-number translation).
- Release(`-O3 -DNDEBUG`): ๋ฐฐํฌ๋ฅผ ์ํ ๋น๋.
- high optimization level, no debug info, code or asserts.
- RelWithDebInfo(`-O2 -g -DNDEBUG`): ๋ฐฐํฌ๋ฅผ ์ํ ๋น๋์ด์ง๋ง ๋๋ฒ๊น
์ ๋ณด ํฌํจ.
- optimized, *with* debug info, but no debug (output) code or asserts.
- MinSizeRel(`-Os -DNDEBUG`): ๋ฐฐํฌ๋ฅผ ์ํ ๋น๋์ธ๋ฐ ์ต์ ํฌ๊ธฐ๋ก ์ต์ ํ.
- same as Release but optimizing for size rather than speed.
2. CMake ์คํํ๊ธฐ: CMakeLists.txt
2.1 CMake ์คํํ๊ธฐ: Make ๋น๋ ์์คํ ์ด์ฉ
CMake ๋ฅผ ์ฌ์ฉํ๋ ๋ชจ๋ ํ๋ก์ ํธ์๋ ๋ฐ๋์ ํ๋ก์ ํธ ์ต์์ ๋๋ ํ ๋ฆฌ์ *CMake ํ์ผ์ด ์์ด์ผ ํฉ๋๋ค. ์ฌ๊ธฐ์ CMake ํ์ผ์ ๋๋ถ๋ถ 'CMakeLists.txt' ๋ผ๋ ์ด๋ฆ์ผ๋ก ์์ฑํ๋ฉฐ, ๋น๋ ํ์ผ์ ์์ฑํ๋๋ฐ ํ์ํ ์ ๋ณด๋ค์ด ๋ค์ด ์์ต๋๋ค.
์ปดํ์ผ ๊ณผ์ : CMakeLists.txt -> Cmake๋ฅผ ์ด์ฉํ์ฌ Makefile ์์ฑ -> Makefile์ ์ด์ฉํ์ฌ ์คํ ํ์ผ ์์ฑ.
// ํ๋ก์ ํธ์ ์ต์๋จ CMakeLists.txt
$ mkdir build; cd build
$ cmake ..
$ make
์ฃผ์!!!: ๋ฐ๋์ ๋น๋ ํ์ผ ์ฉ ๋๋ ํ ๋ฆฌ(/build)๋ฅผ ๋ง๋ ๋ค์์ ํด๋น ๋๋ ํ ๋ฆฌ์์ CMake ๋ฅผ ์คํํฉ์๋ค.
CMake ๋ ์คํ์ ์ฌ๋ฌ๊ฐ์ง ํ์ผ๋ค (์บ์ ์ฉ๋๋ก) ์ ์์ฑํ๋๋ฐ ์ด ๋๋ฌธ์ ํ๋ก์ ํธ ๋๋ ํ ๋ฆฌ๊ฐ ๋์ฅํ์ด ๋ ์ ์์ต๋๋ค.
2.1.1 CMakeList.txt ๋ณ๊ฒฝ ํ ์ฌ๋น๋: rm build/CMakeCache.txt
// pwd: ํ๋ก์ ํธ์ ์ต์๋จ์ CMakeLists.txtํ์ผ์ด ์๋ ๊ณณ
$ cd build
$ rm CMakeCache.txt
- CMakeCache.txt๋ง ์ง์์ ธ๋ cmake .. ์ ์ฌ๋น๋๋จ.
2.1.2 CMakeList.txt ์ด์ธ์ ํ์ผ ๋ณ๊ฒฝ ํ ์ฌ๋น๋: make clean
// pwd: ํ๋ก์ ํธ์ ์ต์๋จ์ CMakeLists.txtํ์ผ์ด ์๋ ๊ณณ
$ cd build
$ make clean
makefile๋ด์ clean ์ต์ ์ผ๋ก clean์ ์ญ์ ๋ ํ์ผ์ ๋ช ์ํฉ๋๋ค.
all: $(BUILD)
clean: ; rm -f *.o $(BUILD)
2.2 CMake: Make ์ด์ธ์ ๋น๋ ์์คํ ์ด์ฉ
CMake ์์ ๋ฐ๋ก ์ค์ ํ์ง ์์๋ค๋ฉด ๋ํดํธ๋ก make ๊ฐ ์ ํ๋์ง๋ง ๊ฒฝ์ฐ์ ๋ฐ๋ผ ๋น๋ ์์คํ ์ ๋ง๋ ๋ค๋ฅธ ๋น๋ ํ๋ก๊ทธ๋จ(sln, vcxproj, MakeFiles, ninja ...)์ ์ ํํด์ผ ํฉ๋๋ค.
$ cmake .. -DCMAKE_GENERATOR=Ninja
์ CMAKE_GENERATOR ์ธ์๋ก ์ํ๋ ๋น๋ ์์คํ ์ ํธ์ถํ๋๋ก ์ ๋ฌํ๋ฉด ๋๋๋ฐ, ์ ์ฒด ๋ชฉ๋ก์ ์ฌ๊ธฐ ์์ ๋ณด์ค ์ ์์ต๋๋ค.
๋ํ์ ์ผ๋ก...
- "Unix Makefiles" (๋ํดํธ)
- "Ninja"
- "Visual Studio 16 2019"
+ ๋น๋ ์์คํ /ํด์ฒด์ธ ์ง์
ํด์ฒด์ธ ํ์ผ: CMake๊ฐ ์ง์ํ๋ ๋ค์ํ ๊ธฐ๋ฅ๋ค์ ์ฌ์ฉํด ๋น๋๋ฅผ ์ํํ ์ ์๋๋ก ๋ฏธ๋ฆฌ ์ง์ ๋ ํ์ผ์ ์๋ฏธํฉ๋๋ค.
cmake --build . # ... ์ง์ ๋ ํด์ ์ฌ์ฉํด ๋น๋๋ฅผ ์งํํ๋ค ...
cmake --build . --parallel # ๋ณ๋ ฌ ๋น๋
cmake --build . --target install # ๋น๋์ ์ฑ๊ณตํ๋ฉด ์ค์น๊น์ง ์งํํ๋ค
cmake --build . --config debug # Debug๋ก ๋น๋
- Android NDK์์๋ ์ฌ๋ฌ ์ํคํ ์ฒ๋ก์ ํฌ๋ก์ค ์ปดํ์ผ์ ํ์ํ ์ค์ ๋ค์ด ์์ฑ๋ android.toolchain.cmake ํ์ผ์ด ํจ๊ป ์ ๊ณต๋๋ฉฐ, CMake๋ฅผ ์ฌ์ฉํ ๋น๋๋ฅผ ์ํ์์ Gradle์ ์ํด์ ์๋์ผ๋ก ์ง์ ํฉ๋๋ค.
- iphone์ ๋์์ผ๋ก ํ๋ ๊ฒฝ์ฐ์๋ https://github.com/leetal/ios-cmake ๋ฅผ ์ฌ์ฉํด XCode ํ๋ก์ ํธ๋ฅผ ์์ฑํ๊ธฐ๋ ํฉ๋๋ค.
- ๋ค๋ฅด๊ฒ๋ https://github.com/Microsoft/vcpkg ์ ๊ฐ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํ์์ ํนํ๋ ํด์ฒด์ธ ํ์ผ์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ๋ ์์ต๋๋ค.
# ... Vcpkg์์ ์ ๊ณตํ๋ cmake ํด์ฒด์ธ์ ๊ฒฝ๋ก๋ก ์ ๊ณตํ๋ค ...
cmake ../ -G "Visual Studio 15 2017 Win64" -DCMAKE_TOOLCHAIN_FILE="X:\Develop\vcpkg\scripts\buildsystems\vcpkg.cmake"
3. CMake ๊ธฐ์ด ๋ฌธ๋ฒ ์ ๋ฆฌ
3.1 ํ์์ ์ธ CMake: ์ต์๋จ CMakeLists.txt ํ์ผ
์ต์ ๋ฒ์ ๋ช ๊ธฐ
๋ชจ๋ CMake ํ์ผ์ ์ต์๋จ์๋ ์ต์ ๋ฒ์ ์ด ๋ช ์๋์ด์ผ ํฉ๋๋ค. ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
cmake_minimum_required(VERSION 3.10)
ํ๋ก์ ํธ ์ค์
์ต์์ CMake ํ์ผ์ ๋ค์ ๋ด์ฉ์ ํฌํจํด์ผ ํฉ๋๋ค.
project(MyProject VERSION 1.0
DESCRIPTION "Very nice project"
LANGUAGES CXX)
- ์คํธ๋ง์ ““ ์ฒ๋ฆฌ
- ๊ณต๋ฐฑ๋ฌธ์๋ ์๋ฏธ๋ฅผ ๊ฐ์ง์ง ์์
- LANGUAGES ๋ C CXX๊ฐ default์ด๋ฉฐ, ๊ทธ ์ธ์๋ CUDA, OBJC, OBJCXX, Fortran ๋ฑ๋ฑ์ด ๊ฐ๋ฅํฉ๋๋ค.
์ค์ ํ์ผ
configure_file(TutorialConfig.h.in TutorialConfig.h)
configure file์ ์ถ๊ฐํ๋ค๋ฉด ๋ฐ๋์ include ๊ฒฝ๋ก๋ฅผ ์ถ๊ฐํด์ฃผ์ด์ผ ํฉ๋๋ค.
target_include_directories(${PROJECT_NAME}
PUBLIC
${PROJECT_BINARY_DIR}/include
)
- configure_file์ ๋ํ ์ธ๋ถ์ ์ธ ๋ด์ฉ์ [CMake] configure_file(): CMake ๋ณ์๊ฐ์ ํ์ผ์ ๋ฐ์!์ ์ฐธ๊ณ ํ๋๋ก ํฉ์๋ค.
๋น๋ ๊ด๊ณ ์ค์ (์์กด์ฑ)
ํ๋ก์ ํธ ๋ด์์ ์ฌ๋ฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋น๋ํ๋ค๋ฉด, ๊ทธ๋ฆฌ๊ณ ์๋ก ์์กด์ฑ์ด ์๋ค๋ฉด ์ด๋ฅผ ์ ์ดํ๋ ๊ฒ๋ ๊ฐ๋ฅํฉ๋๋ค. ์ด ๊ณผ์ ์ ๋ณดํต ํด๋น sub-project๋ค์ ๋ชจ๋ ํ์ธํ ์ ์๋ CMakeList์์ ์ํํ๊ฒ ๋ฉ๋๋ค.
์๋์ ๊ฐ์ ํํ๋ก ํ๋ก์ ํธ๊ฐ ๊ตฌ์ฑ๋์๋ค๊ณ ๊ฐ์ ํ๊ฒ ์ต๋๋ค.
$ tree ./multiple-library-project
./multiple-library-project
โโโ CMakeLists.txt # <--- Root CMakeList
โโโ include
โ โโโ ...
โโโ module1
โ โโโ CMakeLists.txt
โ โโโ ...
โโโ module2
โ โโโ CMakeLists.txt
โ โโโ ...
โโโ test
โโโ CMakeLists.txt
โโโ ...
์๋จ์ CMakeLists.txt ํ์ผ์์ ํ์ ํด๋(module1, module2, test)๋ฅผ ์ถ๊ฐํด์ผ ํฉ๋๋ค.
# multiple-library-project/CMakeLists.txt
add_subdirectory(module1)
add_subdirectory(module2)
add_subdirectory(test)
module2๊ฐ module1์ ๊ธฐ๋ฅ์ ์ฌ์ฉํ๊ณ , test๋ ์ด ๋์ ๊ธฐ๋ฅ์ ๋ชจ๋ ์ฌ์ฉํ๋ค๋ฉด ์ด๋ Root CMake์์ ๋ค์๊ณผ ๊ฐ์ด ๋ช ์ํ ์ ์์ต๋๋ค.
# dependency: from -> { to }
add_dependencies(module1 module2) # `module1` requires `module2`
add_dependencies(test module1 module2) # `test` requires `module1` & `module2`
์ด๋ฅผ ๋ฐํ์ผ๋ก CMake์์ ํ๋ก์ ํธ๊ฐ ์์ฑ๋๋ฉด, ๊ทธ ํ๋ก์ ํธ๋ ์์กด์ฑ์ ๊ณ ๋ คํ์ฌ module1, module2, test ์์๋ก ๋น๋๋ฅผ ์งํํ๊ฒ ๋ฉ๋๋ค.
3.2 ํ๊ฒ(target) & ์์ฑ(property)
- target์ด๋? ํ๋ก๊ทธ๋จ์ ๊ตฌ์ฑํ๋ ์์๋ค(์คํํ์ผ, ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ฑ)
- property๋? ๊ฐ ํ๊ฒ์ ๋ํ ์์ฑ(์ปดํ์ผ ์ต์
, ๋งํนํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ, includeํ ํ์ผ์ ์์น ๋ฑ)
- ๋ชจ๋ CMake ๋ช ๋ น์ ๊ทธ๋ฅ ํ๊ฒ์ ์ ์ํ๊ณ (add_executable), ํด๋น ํ๊ฒ๋ค์ ์์ฑ์ ์ง์ ํ๋ ๋ช ๋ น๋ค (target_compile_options) ๋ก ์ด๋ฃจ์ด์ง๋๋ค.
ํ๊ฒ(Target): ์คํ ํ์ผ ์์ฑ
add_executable(one two.cpp three.h)
- ์ดํ์ ๋์ค๋ .cpp ํ์ผ์ ์ฌ์ฉํด ์คํํ์ผ์ ์์ฑํฉ๋๋ค.
- ์คํํ์ผ๋ช , ์์ค๋ช ์์ผ๋ก ๊ธฐ์ฌํฉ๋๋ค.
- ์์ค๋ ๋ณต์ ๊ฐ๋ฅผ ๊ธฐ์ฌํ ์ ์์ต๋๋ค.
- ํค๋๋ ๋ฌด์๋์ง๋ง, ํน์ IDE๋ ํค๋๊ฐ ๋ช ์๋์ด ์์ด์ผ ์ธ์ํ ์ ์์ผ๋ฏ๋ก ํ์์ ๋ฐ๋ผ ๊ธฐ์ฌํฉ๋๋ค.
ํ๊ฒ(Target): ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์์ฑ
add_library(one STATIC two.cpp three.h)
- add_executable๊ณผ ๊ฐ์ด ๋งจ ์ฒ์์๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ช ์ ๊ธฐ์ฌํ๋ฉฐ, ์ดํ์ ๋์ค๋ .cpp ํ์ผ์ ์ฌ์ฉํด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์์ฑํฉ๋๋ค.
- ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ STATIC, SHARED, MODULE์ ํตํด ์ ์ธํ ์ ์์ต๋๋ค.
- STATIC: ์ ์ ๋งํน ๋ผ์ด๋ธ๋ฌ๋ฆฌ (*.a, *.lib)
- ํ๋ก๊ทธ๋จ ์คํ ํ์ผ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ฝ๋๊ฐ ์ ๋ถ ๋ค์ด ์๋ ๊ฒ์ ๋๋ค.
- SHARED: ๋์ ๋งํน ๋ผ์ด๋ธ๋ฌ๋ฆฌ (*.so, *.dll)
- ํ๋ก๊ทธ๋จ ์คํ ํ์ผ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ํฌํจ๋์ด ์๋ ๊ฒ์ด ์๋๋ผ, ๋ฉ๋ชจ๋ฆฌ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ๋ฐ๋ก ์ฌ๋ผ๊ฐ๋๋ฐ ์ด๋ฅผ ์ฐธ์กฐํ๋ ํํ์ ๋๋ค.
- MODULE: ๋์ ์ผ๋ก ๋งํฌ๋์ง๋ ์์ง๋ง, dlopen ๊ณผ ๊ฐ์ ํจ์๋ก ๋ฐํ์ ์์ ๋ถ๋ฌ์ฌ ์ ์๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋๋ค.
- STATIC: ์ ์ ๋งํน ๋ผ์ด๋ธ๋ฌ๋ฆฌ (*.a, *.lib)
- ์ฐธ๊ณ ๋ก CMake ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋ง๋ค๊ฒ ๋๋ฉด ์์ lib์ ๋ถ์ธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํ์ผ์ ์์ฑํฉ๋๋ค.
+ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ณ์นญ ์์ฑ: ๊ด๋ฆฌ ์ฉ์ด
add_library(project::${PROJECT_NAME} ALIAS ${PROJECT_NAME})
- ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ๊ฐ๊ธ์ ALIAS๋ฅผ ์ถ๊ฐํ์ฌ ์์ฉ *์จ๋ํํฐ ์ ํ๊ณผ ๊ฐ์ ํํ๋ก ๊ด๋ฆฌํด์ฃผ์ธ์.
*์จ๋ํํฐ: ๋ค๋ฅธ ํ์ฌ ์ ํ์ ์ด์ฉ๋๋ ์ํํธ์จ์ด
์ฃผ์!!!: ์๋ ๋ฒ์ ์ CMake ์์๋ ์์ *target_ ์ด ๋น ์ง include_directories, link_directories ์ ๊ฐ์ ๋ช ๋ น๋ค์ด ์ฌ์ฉ๋์๋๋ฐ ์ด๋ ์ต์ ์ CMake ์์๋ ์ฌ์ฉ์ด ๊ถ์ฅ๋์ง ์๋ ๋ช ๋ น๋ค ์ ๋๋ค. ํ์ฌ์ Modern CMake ํจ๋ฌ๋ค์์ ํ๊ฒ๋ค์ ๊ธฐ์ค์ผ๋ก ๋์๊ฐ๊ธฐ ๋๋ฌธ์ ๊ผญ target_* ํํ์ ๋ช ๋ น์ ์ฌ์ฉํ๋๋ก ํฉ์๋ค.
+ ์ผ๋ถ ํ์ผ๋ก ์คํํ์ผ ์์ฑํ๊ธฐ (target_sources)
- add_executable๊ณผ add_library์ ํ๊ณ๋ ์์ค ํ์ผ ๋ชฉ๋ก์ ํ๋ฒ์ ๊ฒฐ์ ํด์ ์ ๋ฌํด์ผ ํ๋ค๋ ์ ์ ๋๋ค.
- ์ด๋ Target๋ค์ด CMakeList ํ์ผ์ ๋๋ถ๋ถ์ ๋ํ๋๊ฒ ๋ง๋ค๋ฉฐ, 2.x ๋ฒ์ CMake๋ค์ด ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ฒ๋ผ List ๋ณ์๋ฅผ ์ฌ์ฉํด ์์คํ์ผ ๋ชฉ๋ก์ ๋ง๋ค์ด์ผ ํ๋ ๋ถํธํจ์ด ์์ต๋๋ค.
- ๋ฐ๋ผ์, CMake 3.x์์๋ Target์ ์์คํ์ผ์ '์ถ๊ฐ'ํ ์ ์๋๋ก target_sources๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
# preview ๊ฐ ๊ตฌํ๋ ์์คํ์ผ์ ์ถ๊ฐํ ์ง ๊ฒฐ์ ํ๋ ๋ณ์
set(USE_PREVIEW true)
# target: my_program
add_executable(my_program
main.cpp
feature1.cpp
)
target_sources(my_program
PRIVATE
feature2.cpp
)
if(USE_PREVIEW)
target_sources(my_program
PRIVATE
feature3_preview.cpp
)
else()
+ ํน์ ์์น์ ํ์ผ ์ผ๊ด ์ถ๊ฐ: include srcs
file(GLOB_RECURSE SRC_FILES CONFIGURE_DEPENDS
${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
)
add_library(shape STATIC ${SRC_FILES})
- GLOB_RECURSE: ๋ง์ผ ํ์ ๋๋ ํ ๋ฆฌ๋ฅผ ํฌํจํ๊ณ ์ถ์ง ์๋ค๋ฉด GLOB_RECURSE ๋์ ์ GLOB ์ ์ฃผ๋ฉด ๋ฉ๋๋ค.
- SRC_FILES: ๋ช ๋ น ๋ด ํฌํจ๋ ํ์ผ๋ค์ ๋ชจ๋ ๋ชจ์์ SRC_FILES ๋ผ๋ ๋ณ์๋ฅผ ๊ตฌ์ฑํ๋ผ๋ ์๋ฏธ๊ฐ ๋ฉ๋๋ค.
- CONFIGURE_DEPENDS: ๋ง์ฝ์ GLOB ์ผ๋ก ๋ถ๋ฌ์ค๋ ํ์ผ ๋ชฉ๋ก์ด ์ด์ ๊ณผ ๋ค๋ฅผ ๊ฒฝ์ฐ (์๋ฅผ ๋ค์ด์ ํ์ผ์ ์ถ๊ฐํ๊ฑฐ๋ ์ง์ ์ ๋) CMake ๋ฅผ ๋ค์ ์คํํด์ ๋น๋ ํ์ผ์ ์ฌ์์ฑ ํ๋ผ๋ ์๋ฏธ๊ฐ ๋ฉ๋๋ค.
- ๋ง์ฝ์ ๋๋ ํ ๋ฆฌ ์์ ํ์ผ์ด ์ถ๊ฐ ๋๋๋ผ๋, cmake .. ์ ๋ค์ ์คํํ ํ์ ์์ด ๊ทธ๋ฅ make ๋ง ์คํํด๋ CMake ๊ฐ ๋ค์ ์คํ๋๋ฉด์ ๋น๋ ํ์ผ์ ์ฌ์์ฑ ํฉ๋๋ค.
์ฐธ์กฐ!!: CMake ์์ ๋ชจ๋ ๋ณ์๋ค์ ${๋ณ์ ์ด๋ฆ} ๊ณผ ๊ฐ์ ์์ผ๋ก ์ฐธ์กฐํฉ๋๋ค.
make ์ ๋น์ทํ๋ฐ, make ๋ ์๊ดํธ () ๋ก ๊ฐ์ธ์ฃผ๋ ๋ฐ๋ฉด CMake ๋ ์ค๊ดํธ {} ๋ก ๊ฐ์ธ์ค๋๋ค.
+ ${CMAKE_CURRENT_SOURCE_DIR}: CMakeLists.txt ๊ฐ ์์นํ ๋๋ ํ ๋ฆฌ, ์ฆ ํ์ฌ ๋๋ ํ ๋ฆฌ๋ฅผ ์๋ฏธ ํฉ๋๋ค.
์์ฑ(Property): compile options
target_compile_options(program PRIVATE -Wall -Werror)
- -Wall : ๋ชจ๋ ๊ฒฝ๊ณ ๋ฅผ ํ์ํฉ๋๋ค.
- -Werror : ๊ฒฝ๊ณ ๋ ์ปดํ์ผ ์ค๋ฅ๋ก ๊ฐ์ฃผํฉ๋๋ค.
+ include(CheckCXXCompilerFlag)
์ปดํ์ผ๋ฌ ์ต์ ์ ์ง์ ํด์ฃผ๊ธฐ ์ ์, ์ปดํ์ผ๋ฌ๊ฐ ํด๋น ์ต์ ์ ์ง์ํ๋์ง ๊ฒ์ฌ๊ฐ ํ์ํ ๊ฒฝ์ฐ๋ ์์ต๋๋ค. CMake์ ๊ธฐ๋ณธ ๋ชจ๋๋ค ์ค์๋ ์ด๋ฅผ ์ง์ํ๋ CheckCXXCompilerFlag๋ผ๋ ๋ชจ๋์ด ์์ผ๋ฉฐ, ๋ค์๊ณผ ๊ฐ์ด ๊ฒ์ฌํฉ๋๋ค.
include(CheckCXXCompilerFlag)
check_cxx_compiler_flag(/std:c++latest cxx_latest)
check_cxx_compiler_flag(-Wall high_warning_level)
- ์ถ๊ฐ์ ์ธ ์ปดํ์ผ ๊ด๋ จ ๋ด์ฉ์ [Github]CMake ํ ๋ ์ชผ์ค์ค๊ธ ๋์์ด ๋๋ ๋ฌธ์ ๋ฅผ ์ฐธ๊ณ ํ๋๋ก ํฉ์๋ค.
์์ฑ(Property): include directories
target_include_directories(one PUBLIC include)
์๊ธฐ ๋ช ๋ น์ด๋ ํ๊ฒ์ ํฌํจํ ๋๋ ํ ๋ฆฌ๋ฅผ ์ถ๊ฐํฉ๋๋ค(๋์ฒด๋ก ํค๋ํ์ผ์ ์ถ๊ฐํ๋ค).
- PUBLIC: ๋ณธ ํ๊ฒ์ ์์กดํ๋ ํ๊ฒ๋ค๋ ํด๋น ๋๋ ํ ๋ฆฌ์ ์ ๊ทผํ ์ ์์ต๋๋ค(์์กด์ฑ ์ ํ).
- PRAIVATE: ๋ณธ ํ๊ฒ์๋ง ํฌํจํด์ผ ํ๋ ๋๋ ํ ๋ฆฌ๋ฅผ ๋ค๋ฅธ ํ๋ก์ ํธ์์ ์ ๊ทผํ ์ ์์ต๋๋ค.
์์ฑ(Property): link library
target_link_libraries๋ฅผ ํตํด ํ๊ฒ์ ์์กด๋์ด ์๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋ช ์ํ๋ฉฐ, ์ฃผ๋ก ๋ด๋ถ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ FetchContent๋ฅผ ํตํด ๋ฐ์์จ ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋งํนํ ๋ ์ฌ์ฉํฉ๋๋ค.
#FetchContent๋ก ๋ฐ์ spdlog์ jsoncpp๋ฅผ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋งํน ์์
(์์กด์ฑ ์ค์ )
target_link_libraries(${PROJECT_NAME}
PUBLIC
spdlog::spdlog jsoncpp_static
PRIVATE
utf8proc
)
๋ค๋ฅธ ํ๋ก์ ํธ์์ ์๊ธฐ์ ${PROJECT_NAME}์ ํด๋นํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋งํนํ ๊ฒฝ์ฐ...
- PUBLIC: ํค๋ํ์ผ์ includeํ๊ธฐ ์ํ ๊ฒฝ๋ก์ ๋น๋ ๊ฒฐ๊ณผ ์์ฑ๋๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ ๊ทผํ ์ ์์ต๋๋ค.
- PRAIVATE: ํด๋น ํ๋ก์ ํธ์์ ์ฌ์ฉํ๊ธฐ ์ํด ์ถ๊ฐํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก ๋ค๋ฅธ ํ๋ก์ ํธ์์ ์ ๊ทผํ ์ ์์ต๋๋ค.
- INTERFACE: ํค๋ ํ์ผ์์๋ง ์ฌ์ฉํ๊ณ ๋ด๋ถ ๊ตฌํ์์๋ ์ฌ์ฉํ์ง ์์ต๋๋ค.
- ๋ฐ๋ผ์...
- ์์กด์ฑ์ด ๊ณต์ ๋์ด์ผ ํ๊ฑฐ๋ ๊ธฐํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ํจ๊ป ์ฌ์ฉํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ผ๋ฉด PUBLIC์ผ๋ก ์ ์ธํ๊ณ ,
- ๋ด๋ถ ๊ตฌํ์๋ง ์ฌ์ฉ๋๊ณ ๊ณต๊ฐ๋์ง ์๋ ๊ฒฝ์ฐ๋ผ๋ฉด PRIVATE์ ๋ฐฐ์นํ๋ ๊ฒ์ด ์ ํฉํฉ๋๋ค.
- ์ถ๊ฐ๋ก...
- FetchContent๋ฅผ ์ด์ฉํ์ฌ ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๊ฐ์ ธ์ค๋ ๋ฐฉ๋ฒ์ ๋ค์ ๊ธ์ ์ฐธ์กฐํ๋๋ก ํฉ์๋ค!
- ์ฐธ๊ณ : [CMake] FetchContent: ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์~
๊ฐ๋จ ์์
๋ค์์ ์๊ธฐ ์ค๋ช ๋ค์ ํฌํจํ๋ ์ต์ํ์ CMake ์์ ์ด๋ฉฐ, ๊ฒฐ๊ณผ๋ก์ 'backlib'์ด๋ผ๋ ์ ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํ์ผ์ด ์์ฑ๋ฉ๋๋ค.
cmake_minimum_required(VERSION 3.22)
# ${PROJECT_NAME}: backlib
project(backlib VERSION 1.0
DESCRIPTION "Util Library"
LANGUAGES CXX C)
# CONFIGURE_DEPENDS: main build system check target to rerun the flagged GLOB commands at build time.
file(GLOB DEPS CONFIGURE_DEPENDS "src/*")
set(ALL_DEPS ${ALL_DEPS} ${DEPS})
# ${PROJECT_NAME}์ autocrypt::${PROJECT_NAME}๋ฅผ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ถ๊ฐ
add_library(${PROJECT_NAME} STATIC ${ALL_DEPS})
# add_library(autocrypt::${PROJECT_NAME} ALIAS ${PROJECT_NAME})
target_include_directories(${PROJECT_NAME}
PUBLIC
include
${PROJECT_BINARY_DIR}/include
)
#FetchContent๋ก ๋ฐ์ spdlog์ jsoncpp๋ฅผ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋งํน ์์
(์์กด์ฑ ์ค์ )
target_link_libraries(${PROJECT_NAME}
PUBLIC
spdlog::spdlog jsoncpp_static
)
3.3 ๋ณ์(Variables)์ ์บ์(Cache)
์ง์ญ๋ณ์(Local Variables) ์ค์
๋ณ์๋ set์ ์ฌ์ฉํด์ ์์ฑํ๋ฉฐ ๋จ์ํ Boolean, ๋ฌธ์์ด, ํ์ผ ๊ฒฝ๋ก, ๋ฆฌ์คํธ ๋ฑ์ ํํํ ์ ์์ต๋๋ค.
๋ํ, unset์ ์ฌ์ฉํด์ ์ ๊ฑฐํ ์ ์์ต๋๋ค.
set(MY_VARIABLE "value")
set(MY_LIST "one" "two")
set(MY_LIST "one;two")
set(MY_BOOL ON)
option(MY_BOOL "message" OFF)
์ด๋ฌํ ๋ณ์๋ฅผ message์ ${}๋ฅผ ์ด์ฉํ๋ฉด ์ถ๋ ฅํ์ฌ ๋ณ์๊ฐ์ ๋ฌธ์์ด๋ก ํ์ธํ ์ ์์ต๋๋ค.
set(CMAKE_BUILD_TYPE Debug)
message(STATUS CMAKE_BUILD_TYPE) # -- CMAKE_BUILD_TYPE
message(STATUS ${CMAKE_BUILD_TYPE}) # -- Debug
message(STATUS "Configuration: ${CMAKE_BUILD_TYPE}") # -- Configuration: Debug
+ message: ์คํฌ๋ฆฝํธ๋ฅผ ์คํํ๋ฉฐ ํด๋น ๋ผ์ธ์ ์์ ๋ ํด๋น ์ ๋ณด๋ฅผ ์ถ๋ ฅํฉ๋๋ค.
message([<mode>] "message text" ...)
<mode> keyword: optional
- NOTICE : <mode> ์๋ต์ default <mode>๊ฐ์ด๋ฉฐ, ์ค์ ์ ๋ณด๋ฅผ ๋ํ๋ด๋ ๋ฉ์ธ์ง๋ก ๊ตฌ๋ถํ์ฌ ์ถ๋ ฅ
- STATUS : ์ํ๋ฉ์ธ์ง ์ถ๋ ฅ ('--'์ ํจ๊ป ๋ฉ์ธ์ง๊ฐ ์ถ๋ ฅ๋จ)
- WARNING : ๊ฒฝ๊ณ ๋ฉ์ธ์ง
- AUTHOR_WARNING : ์คํฌ๋ฆฝํธ ๊ฐ๋ฐ์์ฉ ๊ฒฝ๊ณ ๋ฉ์ธ์ง
- SEND_ERROR : ์ค๋ฅ ๋ฉ์ธ์ง, ์ค๋ฅ๊ฐ ๋๋ ๊ณ์ ์งํํ์ง๋ง ๊ฒฐ๊ณผ๋ฌผ(Makefile)์ ์์ฑํ์ง ์์
- FATAL_ERROR : ์ค๋ฅ ๋ฉ์ธ์ง, ๋น๋์์
์ ์ฆ์ ์ค๋จ
- ์ฃผ์!!! : Makefile ์คํ ์๊ฐ ์๋ cmake๋ก Makefile์ ์์ฑํ ๋ ์ถ๋ ฅ๋๋ ๋ฉ์ธ์ง์ ๋๋ค.
์บ์(Cache) ์ค์
์ปค๋งจ๋ ๋ผ์ธ์ ํตํ ๋ณ์ ์ค์ ์ Cache๋ฅผ ํตํด ์ง์๋ฉ๋๋ค.
set(MY_CACHE_VARIABLE "VALUE" CACHE STRING "Description")
+ ์บ์(Cache) ํ์ธ ๋ฐ ์ค์
$ nano CMakeCaches.txt
$ ccmake ..
- ccmake: MY_CACHE_VARIABLE๊ณผ ๊ฐ์ configuration ์ค์ ๊ฐ์ ํ์ธ ๋ฐ ๋ณ๊ฒฝ ๊ฐ๋ฅ.
- ์ฐธ๊ณ : https://cmake.org/cmake/help/latest/manual/ccmake.1.html
ํ๊ฒฝ๋ณ์(Environment Variables) ์ค์
# SET
set(ENV{variable_name} value)
# GET
$ENV{variable_name}
ํ๋กํผํฐ(Properties) ์ค์
CMake๊ฐ ์ ๋ณด๋ฅผ ์ ์ฅํ๋ ๋ฐฉ์์๋ ๋ณ์ ์ธ์๋ ํ๋กํผํฐ๊ฐ ์์ต๋๋ค. ํ๋กํผํฐ๋ ํ๊ฒ ๋ณ๋ก ์ง์ ๊ฐ๋ฅํฉ๋๋ค.
set_property(TARGET TargetName PROPERTY CXX_STANDARD 11)
set_target_properties(TargetName PROPERTIES CXX_STANDARD 11)
get_property(ResultVariable TARGET TargetName PROPERTY CXX_STANDARD)
3.4 CMake ํ๋ก๊ทธ๋๋ฐ
CMake๋ ์ผ๋ถ ๊ฐ๋จํ ํ๋ก๊ทธ๋๋ฐ์ ์ง์ํฉ๋๋ค.
if ๋ฌธ
if(variable)
# If variable is `ON`, `YES`, `TRUE`, `Y`, or non zero number
else()
# If variable is `0`, `OFF`, `NO`, `FALSE`, `N`, `IGNORE`, `NOTFOUND`, `""`, or ends in `-NOTFOUND`
endif()
# If variable does not expand to one of the above, CMake will expand it then try again
Generator-expressions
target_compile_options(MyTarget PRIVATE "$<$<CONFIG:Debug>:--my-flag>")
๋งคํฌ๋ก(Macros) ๋ฐ ํจ์(Functions)
function(SIMPLE REQUIRED_ARG)
message(STATUS "Simple arguments: ${REQUIRED_ARG}, followed by ${ARGV}")
set(${REQUIRED_ARG} "From SIMPLE" PARENT_SCOPE)
endfunction()
simple(This)
message("Output: ${This}")
- ํจ์(function)์ ๊ด๋ จ๋ ์์ธํ ๋ด์ฉ์ [CMake] function: ๋ฐ๋ณต๋๋ ์์ ์ ํจ์ํํ์!๋ฅผ ์ฐธ๊ณ ํฉ์๋ค.
3.5 ์ฝ๋์ ์ํตํ๊ธฐ: CMakeLists ์ ์๋ ๋ณ์ ์ฝ๋์์ ์ฌ์ฉํ๊ธฐ
CMake๋ configure_file ๋ช ๋ น์ด๋ฅผ ํตํด cpp, hpp๋ฑ ์ฝ๋๋ฅผ ์ง์ ์์ ํ ์ ์์ต๋๋ค. ๊ฐ์ฅ ๋ง์ด ์ฌ์ฉ๋๋ ์์๋ Version.h.in ์ ๋๋ค.
Configure File ์ค์ ํ์ผ ์์ฑ: Version.h.in
#pragma once
#define MY_VERSION_MAJOR @PROJECT_VERSION_MAJOR@
#define MY_VERSION_MINOR @PROJECT_VERSION_MINOR@
#define MY_VERSION_PATCH @PROJECT_VERSION_PATCH@
#define MY_VERSION_TWEAK @PROJECT_VERSION_TWEAK@
#define MY_VERSION "@PROJECT_VERSION@"
Configure File ์ค์ ํ์ผ ๋ช ์
configure_file (
"${PROJECT_SOURCE_DIR}/include/My/Version.h.in"
"${PROJECT_BINARY_DIR}/include/My/Version.h"
)
ํ์ผ์ ๋ด์ฉ์ ์ฝ์ด์ค๋ ๊ฒ๋ ๊ฐ๋ฅํฉ๋๋ค.
# Assuming the canonical version is listed in a single line
# This would be in several parts if picking up from MAJOR, MINOR, etc.
set(VERSION_REGEX "#define MY_VERSION[ \t]+\"(.+)\"")
# Read in the line containing the version
file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/include/My/Version.hpp"
VERSION_STRING REGEX ${VERSION_REGEX})
# Pick out just the version
string(REGEX REPLACE ${VERSION_REGEX} "\\1" VERSION_STRING "${VERSION_STRING}")
# Automatically getting PROJECT_VERSION_MAJOR, My_VERSION_MAJOR, etc.
project(My LANGUAGES CXX VERSION ${VERSION_STRING})
3.6 ๋ค๋ฅธ ํ๋ก๊ทธ๋จ ์คํ์ํค๊ธฐ
๋ค๋ฅธ ํ๋ก๊ทธ๋จ์ ์คํ์ํค๋ ๋ฐฉ๋ฒ์ 2๊ฐ์ง๊ฐ ์์ต๋๋ค.
์ค์ ์๊ฐ(configure time)์ ์ธ๋ถ ํ๋ก๊ทธ๋จ์ ์คํ์ํค๋ ๋ฐฉ๋ฒ: execute_process
find_package(Git QUIET)
if(GIT_FOUND AND EXISTS "${PROJECT_SOURCE_DIR}/.git")
execute_process(COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
RESULT_VARIABLE GIT_SUBMOD_RESULT)
if(NOT GIT_SUBMOD_RESULT EQUAL "0")
message(FATAL_ERROR "git submodule update --init failed with ${GIT_SUBMOD_RESULT}, please checkout submodules")
endif()
endif()
๋น๋ ์๊ฐ(build time)์ ์ธ๋ถ ํ๋ก๊ทธ๋จ์ ์คํ์ํค๋ ๋ฐฉ๋ฒ: add_custom_command...
find_package(PythonInterp REQUIRED)
add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/include/Generated.hpp"
COMMAND "${PYTHON_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/scripts/GenerateHeader.py" --argument
DEPENDS some_target)
add_custom_target(generate_header ALL
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/include/Generated.hpp")
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/include/Generated.hpp DESTINATION include)
3.7 ๋ค๋ฅธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๊ฐ์ ธ์ค๊ธฐ: find_package, FetchContent
์ค์ ์๊ฐ(configure time)์ ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๊ฐ์ ธ์ค๋ ๋ฐฉ๋ฒ: FetchContent
FetchContent_Declare(
<name>
<contentOptions>...
[OVERRIDE_FIND_PACKAGE |
FIND_PACKAGE_ARGS args...]
)
FetchContent_MakeAvilable(<name>)
- `FetchContent_MakeAvailable` was introduced in CMake 3.14
- FetchContent์ ๋ํ ์์ธํ ์ค๋ช ์ [CMake] FetchContent: ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์~ ๋ฅผ ์ฐธ๊ณ ํ์๊ธฐ ๋ฐ๋๋๋ค.
๋น๋ ์๊ฐ(build time)์ ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๊ฐ์ ธ์ค๋ ๋ฐฉ๋ฒ: ExternalProject_Add()
ExternalProject_Add(example
... # Download options, etc.
BUILD_COMMAND ${CMAKE_COMMAND} -E echo "Starting $<CONFIG> build"
COMMAND ${CMAKE_COMMAND} --build <BINARY_DIR> --config $<CONFIG>
COMMAND ${CMAKE_COMMAND} -E echo "$<CONFIG> build complete"
)
3.8 CMake ๊ฐ๋จ ์์
๋ค์์ ์๊ธฐ ์ค๋ช ๋ค์ ํฌํจํ๋ CMake ๊ฐ๋จํ ์์ (์ฃผ์ ํฌํจ) ์ ๋๋ค.
# Almost all CMake files should start with this
# You should always specify a range with the newest
# and oldest tested versions of CMake. This will ensure
# you pick up the best policies.
cmake_minimum_required(VERSION 3.1...3.20)
# This is your project statement. You should always list languages;
# Listing the version is nice here since it sets lots of useful variables
project(
ModernCMakeExample
VERSION 1.0
LANGUAGES CXX)
# If you set any CMAKE_ variables, that can go here.
# (But usually don't do this, except maybe for C++ standard)
# Find packages go here.
# You should usually split this into folders, but this is a simple example
# This is a "default" library, and will match the *** variable setting.
# Other common choices are STATIC, SHARED, and MODULE
# Including header files here helps IDEs but is not required.
# Output libname matches target name, with the usual extensions on your system
add_library(MyLibExample simple_lib.cpp simple_lib.hpp)
# Link each target with other targets or add options, etc.
# Adding something we can run - Output name matches target name
add_executable(MyExample simple_example.cpp)
# Make sure you link your targets with this command. It can also link libraries and
# even flags, so linking a target that does not exist will not give a configure-time error.
target_link_libraries(MyExample PRIVATE MyLibExample)
4. Do & Don't
๋ค์ ํญ๋ชฉ๋ค์ An Introduction to Modern CMake: Do's and Don't, [CMake] Effective Modern CMake ์ ๋ฆฌ๋ฅผ ์ฐธ๊ณ ํ์ฌ ์์ฑํ์์ต๋๋ค. ํ๊ธฐ ๋ชฉ๋ก๋ง์ผ๋ก๋ ์ดํด๊ฐ ์ด๋ ค์ธ ์ ์์ต๋๋ค. ๋ณด๋ค ์ฌ๋์๋ ์ดํด๋ฅผ ์ํ ๊ฒฝ์ฐ ์๋ฌธ์ ์ฐธ์กฐํด์ฃผ์ธ์.
Do
- CMake๋ ์ฝ๋๋ผ๊ณ ์๊ฐํ๊ณ ๊น๋ํ๊ณ ์ฝ์ ์ ์๊ฒ ์ ์งํ์์ค
- target ๊ธฐ๋ฐ์ผ๋ก ์๊ฐํ์์ค
- Your targets should represent concepts. Make an (IMPORTED) INTERFACE target for anything that should stay together and link to that.
- interface๋ฅผ ๋ด๋ณด๋ด์์ค
- Config.cmake ํ์ผ์ ์์ฑํ์์ค
- This is what a library author should do to support clients.
- ALIAS๋ฅผ ์์ฑํ์์ค
- Using add_subdirectory and find_package should provide the same targets and namespaces.
- ๋งคํฌ๋ก ๋์ ํ์ ์ ์ฌ์ฉํ์์ค
- ํจ์๋ช ์ ์๋ฌธ์๋ฅผ ์ฌ์ฉํ๊ณ , ๋ณ์๋ช ์ ๋๋ฌธ์๋ฅผ ์ฌ์ฉํ์์ค
- cmake_policy๋ฅผ ์ฌ์ฉํ๊ณ versions์ ๋ฒ์๋ฅผ ์ค์ ํ์์ค.
- Policies change for a reason. Only piecemeal set OLD policies if you have to.
Don't
- ์ ์ญ ํ์ ์ ์ฌ์ฉํ์ง ๋ง์์ค: link_directories, include_libraries ๋ฑ ์ฌ์ฉํ์ง ๋ง์์ค.
- ๋ถํ์ํ PUBLIC ํ์ ์ ๋ด ํญ๋ชฉ์ ์ถ๊ฐํ์ง ๋ง์์ค
- You should avoid forcing something on users that is not required (-Wall). Make these PRIVATE instead.
- GLOB๋ก ํ์ผ์ ์ ํํ์ง ๋ง์์ค
- Make or another tool will not know if you add files without rerunning CMake.
- Note that CMake 3.12 adds a CONFIGURE_DEPENDS flag that makes this far better if you need to use it.
- ํ๊ฒ ์์ฑ ์์ด LINKํ์ง ๋ง์์ค
- LINK์ PUBLIC/PRIVATE๋ฅผ ์๋ตํ์ง ๋ง์์ค
์ฐธ๊ณ
'Study: DeveloperTools(DevTool) > DevTool: CMake' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[CMake] FetchContent: ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์~ (0) | 2022.06.24 |
---|---|
[CMake] Effective Modern CMake ์ ๋ฆฌ (0) | 2022.06.24 |
[CMake] CMake ์๊ฐ ๋ฐ ํ์์ฑ: Modern CMake 3.23+ (0) | 2022.06.24 |
[CMake] Makefile ๋ฐ CMake์ ํ์์ฑ ์ ๋ฆฌ (2) | 2022.06.24 |
[C++] C++ ๋น๋ ์์คํ (ํด)์๋ ๋ญ๊ฐ ์์๊น? (0) | 2022.06.24 |
https://gist.github.com/luncliff/6e2d4eb7ca29a0afd5b592f72b80cb5c?permalink_comment_id=3037466