|
|||||||
Время создания: 15.02.2017 02:53
Раздел: Компьютер - Программирование - Системы сборки - CMake
Запись: xintrea/mytetra_syncro/master/base/14871164211yiucoedh2/text.html на raw.github.com
|
|||||||
|
|||||||
Введение в CMake CMake — это кроcсплатформенная утилита для автоматической сборки программы из исходного кода. При этом сама CMake непосредственно сборкой не занимается, а представляет из себя front-end. В качестве back-end`a могут выступать различные версии make и Ninja. Так же CMake позволяет создавать проекты для CodeBlocks, Eclipse, KDevelop3, MS VC++ и Xcode. Стоит отметить, что большинство проектов создаются не нативных, а всё с теми же back-end`ами. Пример 1. Hello, World: Для начала напишем простейший хеловорлд: main.cpp #include <iostream> int main(int argc, char** argv) { std::cout << "Hello, World!" << std::endl; return 0; } и файл для сборки: CMakeLists.txt cmake_minimum_required(VERSION 2.8) # Проверка версии CMake. # Если версия установленой программы # старее указаной, произайдёт аварийный выход. add_executable(main main.cpp # Создает исполняемый файл с именем main # из исходника main.cpp Синтаксис CMake похож на синтаксис bash, всё что после символа "#" является комментарием и обрабатываться программой не будет. CMake позволяет не засорять дерево исходных кодов временными файлами — очень просто и без лишних телодвижений сборка производится «Out-of-Source». Создадим пустую директорию для временных файлов и перейдём туда. fshp@panica-desktop:~$ mkdir tmp Теперь запустим команду cmake, передав ей в качестве параметра путь к папке с исходниками: fshp@panica-desktop:~/tmp$ cmake ~/cmake/example_1/ Видим, что в папке появилось несколько временных файлов, необходимых для сборки проекта. fshp@panica-desktop:~/tmp$ make Итак, наша программа собралась. Пример 2. Библиотеки: Усложним пример. foo.h void hello_world(); foo.cpp #include <iostream> void hello_world() { std::cout << "Hello, World!" << std::endl; } main.cpp #include "foo.h" int main(int argc, char** argv) { hello_world(); return 0; } CMakeLists.txt cmake_minimum_required(VERSION 2.8) # Проверка версии CMake. # Если версия установленой программы # старее указаной, произайдёт аварийный выход. project(hello_world) # Название проекта set(SOURCE_EXE main.cpp) # Установка переменной со списком исходников для исполняемого файла set(SOURCE_LIB foo.cpp) # Тоже самое, но для библиотеки add_library(foo STATIC ${SOURCE_LIB}) # Создание статической библиотеки с именем foo add_executable(main ${SOURCE_EXE}) # Создает исполняемый файл с именем main target_link_libraries(main foo) # Линковка программы с библиотекой Переменные могут хранить списки значений, разделённых пробеламитабуляциямипереносами: set(SOURCE main.cpp foo.cpp) set(HEADER main.h foo.h) Оба варианта правильные ${var_name} Итак, эта версия нашего проекта включает в себя одну статическую библиотеку, собираемую из исходников. Если заменить «STATIC» на «SHARED», то получим библиотеку динамическую. Если тип библиотеки не указать, по умолчанию она соберётся как статическая. target_link_libraries(main foo ogg vorbis) Как и при ручной компиляции, имена библиотек указываются без стандартного префикса «lib». Пример 3. Подпроекты: Подпроекты очень удобны, если ваша программа разбита на несколько библиотек или же проект состоит из нескольких программ. CMakeLists.txt cmake_minimum_required(VERSION 2.8) # Проверка версии CMake. # Если версия установленой программы # старее указаной, произайдёт аварийный выход. project(hello_world) # Название проекта set(SOURCE_EXE main.cpp) # Установка переменной со списком исходников include_directories(foo) # Расположение заголовочных файлов add_executable(main ${SOURCE_EXE}) # Создает исполняемый файл с именем main add_subdirectory(foo) # Добавление подпроекта, указывается имя дирректории target_link_libraries(main foo) # Линковка программы с библиотекой foo/CMakeLists.txt cmake_minimum_required(VERSION 2.8) # Проверка версии CMake. # Если версия установленой программы # старее указаной, произайдёт аварийный выход. project(foo) # Название проекта set(SOURCE_LIB foo.cpp) # Установка переменной со списком исходников add_library(foo STATIC ${SOURCE_LIB})# Создание статической библиотеки В файле подпроекта ничего нового для вас нет. А вот в основном файле новые команды: include_directories(foo) main.cpp мы не меняли, а foo.h перенесли. Команда указывает компилятору, где искать заголовочные файлы. Может быть вызвана несколько раз. Хидеры будут искаться во всех указаных директориях. add_subdirectory(foo) Указываем директорию с подпроектом, который будет собран как самостоятельный. Пример 4. Поиск библиотек: CMake обладает достаточно развитыми средствами поиска установленых библиотек, правда они не встроеные, а реализованы в виде отдельных модулей. В стандартной поставке довольно много модулей, но некоторые проекты (например Ogre) поставляют свои. find_package(SDL REQUIRED) if(NOT SDL_FOUND) message(SEND_ERROR "Failed to find SDL") return() else() include_directories(${SDL_INCLUDE_DIR}) endif() ########################################################## find_package(LibXml2 REQUIRED) if(NOT LIBXML2_FOUND) message(SEND_ERROR "Failed to find LibXml2") return() else() include_directories(${LIBXML2_INCLUDE_DIR}) endif() ########################################################## find_package(Boost COMPONENTS thread-mt REQUIRED) if(NOT Boost_FOUND) message(SEND_ERROR "Failed to find boost::thread-mt.") return() else() include_directories(${Boost_INCLUDE_DIRS}) endif() ########################################################## target_link_libraries(${TARGET} ${SDL_LIBRARY} ${LIBXML2_LIBRARIES} ${Boost_LIBRARIES} Думаю, смысл должен быть понятен. Первый и второй блок — поиск библиотеки. Если в системе её нет, выведется сообщение об ошибке и завершается выполнение cmake. Третий блок похож, только он ищет не целый пакет библиотек, а лишь необходимый компонент. Каждый такой автоматизированый поиск определяет после выполнения как минимум 3 переменные: Пример 5. Внешние статические библиотеки и объектные файлы: Внешние имеется ввиду несистемные, поставляемые в бинарном виде. add_library(netutil STATIC IMPORTED) set_property(TARGET netutil PROPERTY IMPORTED_LOCATION Binary/game_client/libnetutil.a) Слово «IMPORTED», указывает, что библиотека берётся извне. target_link_libraries(${TARGET} netutil) Генераторы: Как было сказано в начале, CMake умеет генерировать множество различных видов проектов. fshp@panica-desktop:~/tmp$ cmake ~/cmake/example_3/ -G «KDevelop3 — Unix Makefiles» Заключение: Это не перевод мануала, а результат использования CMake в одном коммерческом проекте. Буду рад, если статья поможет хотя бы одному человеку — на русском языке подобной документации довольно мало. Чем понравился CMake лично мне:
Для Sublime Text есть плагин, добавляющий подсветку синтаксиса CMake, он так и называется — «CMake». |
|||||||
|
|||||||
|