Основи складання проектів на с
Деякий час тому ми з вами познайомилися з Autotools. Незважаючи на те, що Autotools досі використовується в багатьох відомих проектах з відкритим вихідним кодом, інструмент цей важко назвати особливо зручним. Крім того, нормально працює він тільки в * nix системах, а в якомусь Windows користуватися Autotools, скажімо так, досить непросто. Загалом, Autotools - це легаси, і нормальні програмісти в наш час намагаються використовувати CMake або, наприклад, SCons. У цій замітці ми познайомимося з CMake.
Використання CMake в найпростішому випадку виглядає наступним чином. У корені сховища створюється файл CMakeLists.txt приблизно такого змісту:
cmake_minimum_required (VERSION 3.1)
find_library (PTHREAD_LIBRARY pthread)
find_library (PCRE_LIBRARY pcre)
include_directories (include)
set (CMAKE_CXX_STANDARD 17)
set (CMAKE_CXX_STANDARD_REQUIRED on)
set (CMAKE_CXX_FLAGS "$ -Wall -Wextra -Werror")
add_executable (main src / Main.cpp src / HttpServer.cpp)
Хочеться сподіватися, яка рядок тут що означає, пояснювати не потрібно. Потім вихідні складаються в каталог src, а заголовки - в каталог include. Для складання проекту говоримо:
mkdir build
cd build
cmake.
make
Просто, чи не так?
Крім наведеного вище find_library в CMake є ряд скриптів для підключення конкретних бібліотек. Зокрема, підключення OpenGL здійснюється якось так:
find_package (OpenGL REQUIRED)
CMake можна вказати конкретний тип Makefile'ов, які ви хочете отримати на виході:
Зокрема, багато програмістів для прискорення складання проектів вважають за краще використовувати Ninja:
cmake -G Ninja.
ninja -j1
Вибір між отладочной і релізной складанням здійснюється так:
cmake -DCMAKE_BUILD_TYPE = Release -G Ninja.
cmake -DCMAKE_BUILD_TYPE = RelWithDebInfo -G Ninja.
cmake -DCMAKE_BUILD_TYPE = MinSizeRel -G Ninja.
# Debug використовується за умовчанням
cmake -DCMAKE_BUILD_TYPE = Debug -G Ninja.
Замість запуску безпосередньо make або ninja можна сказати щось на кшталт:
cmake --build. --config Release --target main
Можна вибрати конкретний компілятор для складання проекту
cmake -DCMAKE_C_COMPILER = `which gcc` \
-DCMAKE_CXX_COMPILER = `which g ++` -G Ninja.
... а також вказати додаткові прапори компіляції:
cmake -DCMAKE_C_FLAGS = "-O0 -g" -DCMAKE_CXX_FLAGS = "-O0 -g".
cmake -DCMAKE_C_FLAGS = "-O0 -g -fprofile-arcs -ftest-coverage" \
-DCMAKE_EXE_LINKER_FLAGS = "-lgcov".
У світі C / C ++ нерідко буває, що сторонні бібліотеки, які використовують CMake, підключаються до проекту за допомогою сабмодулей Git. Підключення таких бібліотек до проекту здійснюється досить просто:
cmake_minimum_required (VERSION 2.8)
include_directories (deps / algorithms / include)
add_subdirectory (deps / algorithms / src)
add_executable (rbtree_example rbtree_example.c)
target_link_libraries (rbtree_example CAlgorithms)
У свою чергу, у бібліотеки файл src / CMakeList.txt повинен бути приблизно таким:
cmake_minimum_required (VERSION 2.8)
add_library (CAlgorithms STATIC
struct / ilist.c
struct / rbtree.c
struct / htable.c
common / utils.c
)
Взагалі, add_subdirectory може приймати шлях до будь-якого каталогу, в якому є файл CMakeLists.txt. Це дозволяє розбивати проект на підпроекти навіть в рамках одного сховища. Знову ж таки, у випадку з бібліотеками це дозволяє помістити тести в окремий підпроект, який не збиратиметься при підключенні бібліотеки в сторонні проекти.
Наприклад, в корені бібліотеки CMakeList.txt може бути таким:
cmake_minimum_required (VERSION 2.8)
add_subdirectory (src)
add_subdirectory (test)
Безпосередньо тести додаються в проект наступним чином:
cmake_minimum_required (VERSION 2.8)
set (CMAKE_C_FLAGS "$ -O0 -g")
add_executable (test_htable test_htable.c)
target_link_libraries (test_htable CAlgorithms)
add_executable (test_rbtree test_rbtree.c)
target_link_libraries (test_rbtree CAlgorithms)
add_test (test_htable "./test_htable")
add_test (test_rbtree "./test_rbtree")
Запуск тестів здійснюється простою командою:
make test
# Або, з включенням отладочного виведення:
make test ARGS = "-V"
# Або, якщо використовуєте Ninja:
ninja test
... виконаної в каталозі build.
Якщо ж ви використовуєте який-небудь PyTest. просто допишіть в CMakeList.txt щось на кшталт:
find_package (PythonInterp REQUIRED)
add_test (NAME python_test
COMMAND py.test --capture = no $ /tests/run.py)
Висновок тестів пишеться в файл Testing / Temporary / LastTest.log. До речі, подробиці про змінних оточення, доступних в CMake, таких, як CMAKE_SOURCE_DIR, можна знайти тут.
Крім розглянутих вище можливостей часто можна зустріти підтримку збірки проектів з різними можливостями. Зокрема, це використовується в Assimp і LLDB. При складанні проекту опції вибираються так:
cmake -DLLDB_DISABLE_CURSES: BOOL = TRUE.
cmake -DASSIMP_BUILD_ASSIMP_TOOLS = OFF.
Опції зазвичай описують в документації, але в крайньому випадку їх можна подивитися і через curses-інтерфейс:
В рамках одного поста, звичайно, не представляється можливим розглянути всі можливості CMake. Однак представленої вище інформації вам повинно цілком вистачити в 90% випадків. Повноцінні робочі приклади використання CMake ви знайдете, наприклад, в цьому. цьому. а також в цьому репозиторіях на GitHub. Приклади використання опцій і умовних операторів можна знайти в репозиторіях вже згаданих Assimp і LLDB. Ну і, звичайно ж, масу корисного ви знайдете на офіційному сайті CMake.
А чи користуєтеся ви CMake і якщо так, чи використовуєте якісь його можливості, про які не було розказано вище?
Сподобався пост? Поділися з іншими:
(Необхідно включити JS)