Cmake как собрать проект windows

CMake — Учебное пособие

Программисты всего мира отмечают сегодня День программиста

CMake — Учебное пособие

Любой, кто работает в мире UNIX или программ на статически скомпилированных языках, скорее всего, сталкивался с компиляцией программ/библиотек из исходных кодов. Если это не была программа типа «Hello world!», то почти наверняка он также столкнулся с проблемой компиляции полученных двоичных файлов. Сегодня мы представим инструмент, который может вам в этом помочь — Cross Platform Make.

В начале было бы полезно сказать, как выполняется компиляция такого небольшого проекта, так как он понадобится для других вещей, которые я упомяну. Если процесс вам понятен, вы можете сразу перейти к разделу «Что такое CMake ?».

Для начала предположим, что у меня есть простой проект типа helloworld, который считывает то, что мы передаем ему на стандартный ввод, и выполняет эти «команды». Одной из основных команд будет шутка, которая будет печатать случайно выбранную шутку из своей «базы данных». Загрузите исходные коды.

Структура файла выглядит примерно так:

А в command.h есть класс команды. Здесь он наследует классы шутки (заголовок в шутке.h и реализация в шутке.cpp) и сообщения (сообщение.h, сообщение.cpp). Кроме того, main.cpp включает в себя все заголовочные файлы. Итак, что насчет этого?

Если бы мы сходили с ума и использовали GCC, мы могли бы просто набрать g++ src/joke.cpp src/main.cpp src/message.cpp -o hello , что бы скомпилировать и слинковать все для нас, и мы бы посмеялись. в. И с такой маленькой глупостью, наверное, окупится. Однако необходимо осознавать, что компиляция является процессоро- и времязатратной операцией, и поэтому не стоит каждый раз компилировать все заново. Лучшекомпилировать только то, что нужно, исвязать его с объектными файлами, которые уже были скомпилированы ранее и чьи исходные файлы не изменились с тех пор.

Программисты поняли это давным-давно, поэтому в 1977 году в Bell Labs была написана программа make. Его конфигурационный файл представляет собой так называемый Makefile, чей синтаксис (в двух словах) выглядит следующим образом:

Как действие, так и его зависимости могут быть файлами или именами других действий. Что касается файлов, то make проверяет, изменились ли они, и если нет, то не выполняет команды для этого действия — если файлы не изменились, этого делать не нужно.

Как будет выглядеть Makefile для нашего проекта?

Теперь будет компилироваться только то, что нужно.

Однако, несмотря на то, что make был действительно отличным инструментом, начали появляться проблемы. Некоторым не понравилось, например. что команды должны быть отступом ровно на одну вкладку любой ценой — и если это не так, make выдал вам прекрасное сообщение об ошибке. Другие говорили, что написание Makefile по-прежнему одно и то же, просто рутина — и, в конце концов, это все еще просто компиляция каждого исходного файла, а затем каким-то образом их всех — в библиотеки, в исполняемую программу. Но, вероятно, хуже всего то, что написанные от руки файлы Makefile обычно не очень переносимы, потому что каждая операционная система может иметь файлы заголовков, библиотеки и даже команды — двоичные файлы, расположенные в другом месте.

Читайте также:  Как отключить windows на digma

Вот почему были разные проекты, которые могли генерировать файлы Makefile. В мире UNIX наиболее известными, вероятно, являются GNU Autotools , которые используют различные макросы для создания сценария оболочки configure. А после запуска будет генерировать файлы изразных скелетов, в том числе и Makefiles. Здесь известна «святая троица»: ./configure; макияж, мириться; make install , который устанавливает проекты с помощью GNU Autotools .

Что такое CMake ?

Теперь мы можем собраться вместедля самого CMake . Если вы где-то видели сравнение с GNU Autotools , это не случайно. Потому что по сути оба делают одно и то же. Однако главное отличие состоит в том, что CMake , в отличие от GNU Autotools , может делать больше, чем просто Makefile. В конце концов, это кроссплатформенная разработка! Таким образом, в дополнение к файлам Makefile он также может генерировать Visual Studio, Kdevelop3, Code::Blocks и другие файлы проекта. И возможности включения других практически не ограничены благодаря его модульной архитектуре.

Он также не генерирует, как GNU Autotools , shell-скрипт, но вам необходимо иметь на машине его бинарник, который читает конфигурационный файл CMakeLists.txt и генерирует требуемый тип выходного проекта файл из него.

(Примеры в статье протестированы на CMake версии 2.6.3.)

Проект Helloworld и CMake

Итак, как будет выглядеть файл CMakeLists.txt для нашего небольшого проекта? Все просто:

Да, это все. Как видите, для достижения того же результата нам просто нужно написать намного меньше строк. Но главное, мы также получаем возможность позволить CMake сгенерировать, например, файл проекта Visual Studio и скомпилировать в нем исходники — не меняя ни одной буквы в CMakeLists.txt.

Файл CMakeLists.txt содержит вызов формы name(arguments) , где аргументы представляют собой строки буквенно-цифровых (плюс некоторые другие) символов, разделенные пробелами (если аргумент должен содержать пробел, просто окружитеего содержимое кавычки).

До сих пор мы видели два вызова, а именно PROJECT() и ADD_EXECUTABLE(). (Имена нечувствительны к регистру.) PROJECT() принимает имя проекта в качестве первого аргумента. В качестве дополнительных аргументов можно добавить используемые в проекте языки программирования (см. документацию).

ADD_EXECUTABLE() сначала передается целевое имя дляисполняемый файл для создания. Остальные аргументы представляют собой список исходных кодов, из которых можно построить исполняемый файл.

Теперь мы можем перейти к самой сборке. Если вы используете Windows , вместе с CMake распространяется графическое приложение, позволяющее настроить сборку и создать необходимые файлы. Если вы работаете в UNIX , CMake предлагает интерфейс ncurses , аналогичный интерфейсу в Windows — если в вашей системе двоичный файл имеет стандартное имя и находится в $PATH, просто запустите ccmake. В противном случае генерация из командной строки выглядит примерно так (при условии, что вы находитесь в папке, где находится CMakeLists.txt):

Как видите, сначала мы создали каталог сборки, куда будут помещаться сгенерированные и скомпилированные файлы. Это так называемая «сборка вне исходного кода». Если бы мы не создавали каталог сборки и запускали cmake непосредственно из каталога исходного кода, это была бы так называемая «сборка в исходном коде». Но второй метод не очень рекомендуется, потому что CMake создаст беспорядок файлов в текущей папке, которые потом придется удалять вручную — это только испортит исходники. В зависимости от того, что вы хотите создать с помощью CMake , теперь вы можете начать процесс сборки. Если целью был UNIX Makefile , то это будет:

Читайте также:  Как панель персонализации для windows

По завершенииmake в каталоге сборки должен быть исполняемый файл hello. Начнем с:

И мы можем наслаждаться тем, как все у нас работает (или, что еще хуже, не работает).

CMake предлагает, помимо сборки, возможность установки скомпилированных (и других) файлов. Это делается вызовом INSTALL() в CMakeLists.txt:

Во-первых, этот вызов принимает то, что мы хотим установить в любом случае. TARGETS сообщает, что это цели, созданные в CMakeLists.txt (например, с помощью ADD_EXECUTABLE() ),другие параметры включают FILES , который сообщает INSTALL(), что мы хотим установить отдельные файлы, см. документацию для получения дополнительной информации. Другие аргументы — это список именно тех целей или файлов, которые эта установка должна охватывать. Затем INSTALL() принимает дополнительные аргументы, указывающие, что делать с целевыми объектами/файлами. В нашем случае мы указываем, что для исполняемых программ ( RUNTIME ) их расположение ( DESTINATION ) должно быть установлено в каталог bin. Каталог считается относительно CMAKE_INSTALL_PREFIX . В системах UNIX по умолчанию установлено значение /usr/local. Итак, если мы снова запустим в папке сборки CMake , а затем скажем make собрать цель установки:

В /usr/local/bin мы должны найти исполняемый файл hello. Если у вас есть /usr/local в $PATH, то просто введите hello и программа запустится.

Если вы хотите, чтобы файлы были установлены в другом месте, просто измените CMAKE_INSTALL_PREFIX :

Создание библиотек

Помимо создания двоичных файлов, нам также иногда нужно создать библиотеку, которую могут использовать другие библиотеки/программы. Если бы CMake не поддерживал это, это было бы не очень полезно. Допустим, мы написали какую-то действительно крутую библиотеку, котораяпозволяет загружать файл целиком в вектор строк, которые затем сортируются, и мы хотим сделать ее доступной для других — чтобы они могли наслаждаться нашим красивым кодом, а мы — чувствовать хорошо о том, как мы помогаем сообществу открытого исходного кода. Загрузите исходные коды.

Каталог include содержит файлы заголовков, которые должны быть установлены, и используемые файлы исходного кода в библиотеке. В src находится единственный файл — file_sort.cpp — с кастомной реализацией всей нашей библиотеки (вся наша библиотека состоит из одной функции). И, конечно же, такая библиотека должна идти вместе с пакетом тестов, поэтому они у нас тоже есть в каталоге test. быстрая сортировка.cppпроверяет функциональность нашего алгоритма сортировки, basic.cpp, в свою очередь, проверяет, делает ли наша библиотечная функция file_sort() то, что должна. На этот раз CMakeLists.txt будет немного длиннее, поэтому давайте разберем его пошагово:

Как обычно, мы начинаем с определения проекта — PROJECT(). Но теперь у нас есть новинка: конструкция MACRO() … ENDMACRO() , которая загрузит для нас команды в макрос, который мы потом сможем использовать. Первый аргумент — это имя макроса, за которым следуют имена аргументов самого макроса. Здесь у нас есть только один именованный аргумент — NAME .

Наш макрос CREATE_LIBRARY состоит из пяти вызовов. ADD_LIBRARY() создает для нас цель сборки для библиотеки, где первый аргумент — это имя цели, за которым следует необязательный аргумент типа библиотеки (SHARED — общая, STATIC — статическая), а остальные — имена файлов исходного кода. Поскольку мы находимся в макросе, мы используем переменную $ , созданную при вызове макроса, в качестве имени. Вместо списка исходников у нас есть $ , это остальные безымянные аргументы привызове макроса — так что для нас это будет список исходников. Сначала создаем разделяемую библиотеку, затем статическую. SET_TARGET_PROPERTIES() устанавливает здесь, чтобы обе библиотеки имели одинаковое имя. И последний вызов, INSTALL() , сообщает CMake , что скомпилированные библиотеки должны быть установлены в каталог lib, опять же относительно CMAKE_INSTALL_PREFIX — опция с ARCHIVE устанавливает каталог для статических библиотек, LIBRARY для общих.

Читайте также:  Как открыть установочный диск windows 7

После создания нашего макроса CREATE_LIBRARY() мы устанавливаем включаемый каталог для добавления в INCLUDE_PATH компилятора, вызывая INCLUDE_DIRECTORIES() . А теперь вызовем сам макрос.

Как я уже сказал, INSTALL() сначала принимает то, что мы хотим установить. На этот раз это папка include и все заголовочные файлы в ней ( *.h ).

Теперь давайте перейдем ктестирование:

Для создания каких-либо целей тестовой сборки мы должны сначала вызвать ENABLE_TESTING() . Затем мы создаем тестовые двоичные файлы (используя ADD_EXECUTABLE()). Тест функциональности Quicksort не работает с нашей библиотекой как таковой (он включает только заголовочный файл quicksort.h и он был добавлен в INCLUDE_PATH ранее), но второй тест работает, поэтому мы должны слинковать его со свежескомпилированной библиотекой. — с помощью TARGET_LINK_LIBRARIES(). Первый аргумент — цель сборки, остальные — библиотеки — у нас есть только одна.

ADD_TEST() добавляет тест. Он принимает имя теста, имя двоичного файла или аргументы командной строки – здесь не используются.

Последний вызов — это ADD_CUSTOM_COMMAND() , который в данном случае подключается к цели basic_test и копирует файл, необходимый для этого теста.

Условный перевод

Условный перевод — это еще одна важная вещь для кросс-платформенных приложений. Если, например, наше приложение будет иметь графический интерфейс и мы хотим, чтобы оно работало как под Windows , так и под Mac OS X и на машинах с X Server , для каждой платформы нужно будет скомпилировать свой (если только мы не используем кроссплатформенный инструментарий). Допустим, у нас будет следующая файловая структура:

Затем мы можем скомпилировать нашу программу следующим образом:

Условная конструкция IF(), вероятно, знакома всем, кто программирует. Такие переменные, как UNIX , APPLE и WIN32, определяются в соответствии с платформой, на которой работает CMake . Вызов MESSAGE() может вывести сообщения, которые мы определяем, на экран, первым аргументом является тип сообщения — я думаю, FATAL_ERROR говорит обо всем этом.

Другой тип условного перевода — это возможность, когда наше приложение может работать без библиотеки, но наличие этой библиотеки может добавить некоторую функциональность. Если вы знаете GNUAutotools , так там в основном сделано так, что есть скелет файла config.h (файл config.h.in), в который при генерации записываются значения различных макросов. CMake тоже может это сделать:

OPTION() дает пользователю возможность выбрать, включать ли эту опцию в Windows или в ccmake. CONFIGURE_FILE() принимает в качестве аргументов полный путь к заголовочному файлу конфигурации скелета (в нашем случае это config.h.cmake в исходном каталоге) и полный путь к выходному файлу (config.h в каталоге сборки). Вот как выглядит файл config.h.cmake:

CMake заменяет #cmakedefine WITH_FOO на #define WITH_FOO, если WITH_FOO включен, или на /*#undef WITH_FOO*/, если нет.

Существуют различные вызовы CHECK_* для заголовочных файлов ибиблиотек, см. вики.

И последняя проблема заключается в том, что в разных системах библиотеки/заголовочные файлы могут находиться в разных местах. CMake также имеет для этого вызова: FIND_LIBRARY() , FIND_PATH() и т. д., подробнее в документации.

Компиляция и подкаталоги

Иногда хорошо, если исходный код все же разделен на подкаталоги. Это также можно организовать в CMake . Рассмотрим структуру каталогов:

Поделиться с друзьями
ОС советы