Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Система построения проектов CMake. Учебник.pdf
Скачиваний:
0
Добавлен:
08.09.2026
Размер:
2 Мб
Скачать
☆
2.10. Команды добавления специальных целей
f
NEWLINE_STYLE hстильig)
hстильi F UNIX
Команда configure_file() предназначена для генериро­вания текстового файла по заданному входному файлу-образцу. Функциональность команды аналогична средствам системы по­строения Autotools (п. 1.3.2), при помощи которых можно гене­рировать заголовочные и make-файлы по их шаблонам. Вход­ной файл копируется в выходной, при этом специальные кон­струкции в нём заменяются в соответствии со значениями пе­ременных CMake. Кроме этого, в генерируемый проект добавля­ется правило построения, которое заставляет заново запускать инструмент CMake для повторной генерации после изменения
 
DOS
 
WIN32
  
LF
  
CRLF
входного файла.
Относительный путь для входного файла интерпретиру­ется по отношению к каталогу текущего подпроекта (перемен­ная CMAKE_CURRENT_SOURCE_DIR), для выходного — к текущему каталогу построения (CMAKE_CURRENT_BINARY_DIR). Для выход­ного файла можно указать существующий каталог, в этом слу­чае файл будет записан в него с тем же именем, что и входной файл.
Замене будут подвержены следующие конструкции вход­ного файла:
— Конструкция @hимя_переменнойi@ заменяется в выходном
файле значением переменной с соответствующим именем
(пустой строкой, если переменная не определена).
161
2. Основы языка CMake
— Аналогично, конструкция ${hимя_переменнойi}.
— Конструкция:
#cmakedefine hимя_переменнойi hстрокаi
будет заменена на:
#define hимя_переменнойi hпреобразованная_строкаi
если значение переменной истинно в соответствии с табл. 2.1, и на строку:
/* #undef hимя_переменнойi */
если ложно. Правила преобразования также применяются к определению символа препроцессора (hстрокаi).
— Аналогично, в зависимости от истинности или ложности
значения, конструкция:
#cmakedefine01 hимя_переменнойi
будет заменена на:
#define hимя_переменнойi h1_или_0i
При помощи необязательных аргументов, передаваемых
команде, можно настроить способ преобразования файла:
— Передача аргумента COPYONLY приводит к обычному копи-
рованию файла без преобразований его содержимого.
162
2.10. Команды добавления специальных целей
— Передача ESCAPE_QUOTES приводит к добавлению сим-
волов «\» перед каждым символом двойной кавычки
во вставляемые значения переменных. Это может быть
необходимо для формирования в выходном файле на язы-
ках C/C++строковых литералов.
— Передача @ONLY приводит к замене только конструкций ви-
да @...@. Это может быть необходимо для генерирования
по образцу сценариев CMake, где конструкции ${...} мо-
гут использоваться при работе с переменными.
— После аргумента NEWLINE_STYLE можно указать способ раз-
деления строк: при помощи символов "\r\n" (CRLF, DOS,
WIN32) или "\n" (LF, UNIX). Этот аргумент несовместим с ар-
гументом COPYONLY.
ПРИМЕР Пусть требуется добавить возможность для разрабатываемой программы вывода на печать своей версии — той, которая ука­зана после аргумента VERSION команды project() (п. 2.4.2) в файле описания проекта.
Этот номер версии хранится в специальной переменной CMake с именем PROJECT_VERSION. Передать эту информацию в исходный код программы можно при помощи команды configure_file(). Чтобы генерируемый файл был как можно меньше по объёму, можно реализовать конфигурирование за­головочного файла, который затем будет подключаться в коде программы. Таким образом, структура каталога проекта может быть такой, как представлено на рис. 2.10.
163
2. Основы языка CMake
hкаталог проектаi
ex-version.cpp
config.h.in ..... обрабатывается CMake (configure_file())
CMakeLists.txt
Рис. 2.10. Структура каталога проекта с шаблоном
конфигурируемого файла
Содержимое файла config.h.in:
#cmakedefine PROJECT_VERSION "@PROJECT_VERSION@"
Если значение переменной PROJECT_VERSION ложно или не определено, в результате конфигурирования будет создан файл со следующим содержанием:
/* #undef PROJECT_VERSION */
Если же в переменной содержится правильный номер вер­сии, например «1.0», будет сгенерировано следующее содержи­мое выходного файла:
#define PROJECT_VERSION "1.0"
Так как оставшаяся часть строки в файле шаблона после имени переменной тоже содержит конструкцию конфигуриро­вания ("@PROJECT_VERSION@"), при формировании выходного файла она также будет обработана, заменившись значением пе­ременной.
Содержимое файла ex-version.cpp:
#include "config.h"
164
2.10. Команды добавления специальных целей
#include <iostream>
const char g_acszVersion[] =
#ifdef PROJECT_VERSION
PROJECT_VERSION;
#else
"<unknown version>";
#endif
int main()
{
std::cout <<
"Version: " << g_acszVersion << std::endl;
}
Здесь в начале подключается файл config.h, который должен быть сгенерирован в выходном каталоге и содержать (или не содержать) определение символа PROJECT_VERSION. Далее при определении строкового константного массива g_acszVersion директивами препроцессора проверяется, был ли определён этот символ. Если да, то массив иници­ализируется литералом, который является определением PROJECT_VERSION, иначе — строкой «неизвестная версия».
Содержимое файла CMakeLists.txt:
cmake_minimum_required(VERSION 3.0)
165
2. Основы языка CMake
# project(ex-version)
project(ex-version VERSION 1.0)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
configure_file(
config.h.in config.h)
add_executable(
ex-version ex-version.cpp config.h.in)
Здесь в команде project() устанавливается версия проек­та. Чтобы эта возможность была доступной, выше устанавлива­ется совместимость с минимальной версией CMake 3.0. Чтобы при компиляции добавляемой цели исполняемого файла был найден генерируемый в выходном каталоге файл config.h, спе­циальной переменной CMAKE_INCLUDE_CURRENT_DIR устанавли­вается значение истины.
В последней строке файл config.h.in добавляется к спис­ку исходных файлов цели исполняемого файла при помощи ко­манды add_executable() (п. 2.5.1). Во время построения этот файл не будет обрабатываться инструментами компилятора, од­нако будет отображаться в списке исходных файлов при работе с интегрированными средами. ∗

2.10.2. add_test(), enable_testing()

add_test(
NAME hимя_тестаi
166
2.10. Команды добавления специальных целей
g
COMMAND hкомандаifhаргумент1i ... hаргументni
f
CONFIGURATIONS hконфигурация1i ... hконфигурацияni
f
WORKING_DIRECTORY hкаталогig)
enable_testing()
Команда add_test() добавляет тест к проекту.
— При помощи аргумента NAME определяется имя теста.
— При помощи аргумента COMMAND определяется команда
вместе с аргументами, которая реализует тест. В случае
g
успешного прохождения теста команда должна передать
системе код возврата, равный 0. Аргумент hкомандаi мо­жет быть либо путём к исполняемому файлу, либо име­нем цели, определённой ранее при помощи команды add_executable() (п. 2.5.1). В последнем случае путь к со­здаваемому при помощи цели исполняемому файлу будет использован в качестве команды, реализующей тест.
— После необязательного аргумента CONFIGURATIONS можно
указать список конфигураций, которыми будет ограниче-
но генерирование теста.
— После необязательного аргумента WORKING_DIRECTORY
можно задать путь к рабочему каталогу исполняемой команды, который определяет одноимённое свойство теста. По умолчанию в качестве рабочего каталога выбира­ется подкаталог построения, соответствующий текущему каталогу подпроекта.
167
2. Основы языка CMake
По умолчанию выполнение команды add_test() не вы­зывает никаких действий. Добавление тестов при помощи этой команды выполняется только после исполнения коман­ды enable_testing(). Эта команда должна вызываться в фай­ле CMakeLists.txt для проекта верхнего уровня. В этом слу­чае в генерируемом описании проекта создаётся дополнитель­ная цель, которая называется test при использовании системы make, проект RUN_TESTS для Microsoft Visual Studio и т. д. При за­пуске цели в случае неудачного исполнения какого-либо теста (с ненулевым кодом возврата) утилита make или подобная ей сама завершится с ненулевым кодом возврата. Это позволяет ор­ганизовать автоматическое тестирование проекта при построе­нии.
В определении правил для цели тестирования использу­ется вызов утилиты ctest из состава CMake. Вместо исполне­ния цели тестирования системой построения можно вызвать эту команду непосредственно. В этом случае появляется возмож­ность передать ей дополнительные аргументы командной стро­ки, предоставляющие расширенные возможности (определение тайм-аута, выбор подмножества тестов и т. д.). При использо­вании инструмента make дополнительные аргументы утилите ctest можно также передать при помощи переменной окруже­ния ARGS (см. пример ниже).
Тестирование является важной составной частью процесса разработки программного обеспечения. Автоматические тесты служат двум целям:
168
2.10. Команды добавления специальных целей
— пользователю программного пакета они предоставляют
возможность проверить корректность построения пакета в его системе;
— разработчику программного проекта, вносящему измене-
ния в исходный код, они позволяют убедиться, что эти из­менения не нарушают прежней функциональности.
Автоматическое тестирование реализовано в описаниях проектов для многих библиотек с открытым исходным кодом, выполняющих математические расчёты (GMP3, LAPACK4и т. д.). CMake облегчает создание подобных целей тестирования. При разработке многих сложных программных проектов оправдан­но внедрение практики, в соответствии с которой любые изме­нения от разработчиков попадают в центральный репозитарий кода только после успешного прохождения построения и тести­рования версии с предлагаемыми изменениями. Для автомати­зации этого процесса существуют различные средства, напри­мер система обзора кода Gerrit5. Таким образом, использование подобных систем совместно с CMake позволяет организовать ав­томатическое тестирование изменений кода перед помещени­ем его в основную ветвь хранилища.
ПРИМЕР Пусть проект библиотеки имеет структуру, изображённую на рис. 2.11.
3
https://gmplib.org/ (дата обращения: 11.01.2015).
4
http://www.netlib.org/lapack/ (дата обращения: 11.01.2015).
5
https://code.google.com/p/gerrit/ (дата обращения: 11.01.2015).
169
2. Основы языка CMake
mylib .............................................. каталог проекта
lib ............................... подкаталог кода библиотеки
mylib.cpp
mylib.h
CMakeLists.txt ...............описание проекта библиотеки
test .........................................подкаталог тестов
mylib_test.cpp CMakeLists.txt ..описание проекта тестового приложения
CMakeLists.txt ..............описание проекта верхнего уровня
Рис. 2.11. Структура каталога проекта с библиотекой
Пусть код библиотеки для примера выглядит следующим
и тестом
образом:
Файл mylib.cpp:
int answer()
{
return 42;
}
Файл mylib.h:
#ifndef MYLIB_H__
#define MYLIB_H__
int answer();
#endif // MYLIB_H__
Файл CMakeLists.txt для подпроекта библиотеки:
170
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]