Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Система построения проектов CMake. Учебник.pdf
Скачиваний:
0
Добавлен:
08.09.2026
Размер:
2 Мб
Скачать
☆
2.6. Команды настроек целей
сгенерировать более эффективный код, желательно объявле­ние этих функций с атрибутом __declspec (dllimport). Что­бы обойтись одним заголовочным файлом, обычно в таких слу­чаях используются директивы препроцессора. Таким образом, окончательная версия заголовочного файла может быть следу­ющей:
#ifndef MY_DLL_H__
#define MY_DLL_H__
#ifdef _MSC_VER
// Если используется Microsoft Visual C
++
#ifdef MY_DLL_BUILD
// Если файл подключается из проекта библиотеки
#define MY_DLL_INTERFACE __declspec (dllexport)
#else // MY_DLL_BUILD
// Если файл подключается из проекта клиента
#define MY_DLL_INTERFACE __declspec (dllimport)
#endif // MY_DLL_BUILD (else)
#else // _MSC_VER
// Если используется любой другой компилятор
#define MY_DLL_INTERFACE
#endif // _MSC_VER (else)
int MY_DLL_INTERFACE my_dll_f();
// ...
#endif // MY_DLL_H__
111
2. Основы языка CMake
Если определён символ препроцессора MY_DLL_BUILD (предполагается, что он определён при построении биб­лиотеки и не определён во всех остальных проектах), символ MY_DLL_INTERFACE, который используется в объ­явлениях экспортируемых функций, определяется как
__declspec (dllexport), в противном случае — как __declspec (dllimport). Теперь описание цели библиоте-
ки может выглядеть следующим образом:
add_library(my_dll SHARED my_dll.cpp my_dll.h)
target_compile_definitions(
my_dll
PRIVATE -DMY_DLL_BUILD)
set(CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE ON)
Для определения символа MY_DLL_BUILD в цели использу­ется команда target_compile_definitions() (п. 2.6.4). Исполь­зование в ней аргумента PRIVATE приводит к тому, что сим­вол не будет определён в других целях, подключающих биб­лиотеку. В отличие от команды add_definitions() (п. 2.6.3), команда target_compile_definitions() не делает символ MY_DLL_BUILD определённым для других целей текущего под­проекта.
Описание цели исполняемого файла, использующего дина­мическую библиотеку (в текущем или отдельном подпроекте), может быть следующим:
112

2.7. Команды обработки данных

add_executable(my_prog my_prog.cpp)
target_link_libraries(my_prog my_dll)
Команда target_link_libraries() транзитивно пере­носит интерфейсные требования проекта my_dll в проект my_prog. В данном случае эти требования представляют собой каталог библиотеки, который нужно использовать для поиска заголовочных файлов (включается установкой специальной пе­ременной CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE, п. 2.6.2). Определение символа MY_DLL_BUILD в эти требования не вхо­дит, что и требовалось. ∗

2.6.8. add_dependencies()

add_dependencies(
hимя_целиifhимя_цели1i ... hимя_целиnig)
Команда устанавливает отношение зависимости при по­строении заданной цели от других. Команда аналогична ко­манде target_link_libraries() (п. 2.6.7) за исключением то­го, что её аргументами могут быть только имена целей и что она не устанавливает зависимостей по подключению библио­тек во время компоновки. По сравнению с ней эта команда применяется не так часто. Как правило, она используется при установлении зависимостей для целей, созданных командой add_custom_target() (п. 2.10.4).
113
2. Основы языка CMake
2.7. Команды обработки данных
2.7.1. set(), unset(), option()
set(
hимя_переменнойifhзначение1i ... hзначениеnig)
set(
hимя_переменнойi hзначениеi
f
f
CACHE hтипi hстрока_описанияifFORCE
PARENT_SCOPE
g g
g
)
hтипi F
FILEPATH
unset(hимя_переменнойifCACHE
option(
hимя_переменнойi hстрока_описанияifhзначениеig)
 
PATH
 
STRING
  
BOOL
  
INTERNAL
PARENT_SCOPEg)
  
Первый вариант команды set() предназначен для при-
сваивания заданной переменной списка из заданных значений
(п. 2.2.2). Таким образом, переменной будет присвоено значение
«hзначение1i; . . . ;hзначениеni».
Второй вариант команды set() при указании аргумента
CACHE или PARENT_SCOPE предназначен для установки значения
114
2.7. Команды обработки данных
переменной в другой области действия (п. 2.2.3). В этом случае переменная не может быть переменной окружения.
— При помощи необязательного аргумента CACHE указывает-
ся, что команде следует осуществлять присваивание пере-
менной кэша. После этого аргумента указывается тип пе-
ременной и строка описания, которая будет использова-
на в качестве информации о переменной в утилите CMake
с оконным пользовательским интерфейсом. Тип перемен-
ной используется исключительно для удобства и влияет
на способ редактирования значения переменной, предо-
ставляемый графической утилитой CMake. Возможны сле-
дующие значения типов:
FILEPATH: в переменной хранится путь к файлу. Для редак-
тирования возможно использовать диалоговое окно выбора файла.
PATH: в переменной хранится путь к каталогу. Для редак-
тирования возможно использовать диалоговое окно выбора каталога.
STRING: в переменной хранится строка общего назначе-
ния. При редактировании используется обычное поле ввода строки.
BOOL: в переменной хранится логическое значение
(п. 2.2.2). Для редактирования будет использовано поле «выключателя».
INTERNAL: утилита CMake не будет отображать информа-
ции об этой переменной. Предполагается, что пере-
115
2. Основы языка CMake
менная используется для внутренних целей и должна храниться в кэше.
После строки описания может быть указан необязатель­ный аргумент FORCE. Его использование приводит к тому, что переменной будет присвоено значение в любом слу­чае, даже если она уже находится в кэше. По умолчанию, если переменная уже там есть, присваивания не происхо­дит. Такое поведение команды set() подходит в большин­стве случаев, так как позволяет сохранять ранее отредакти­рованные значения кэша. Также при присваивании будет удалена из текущей области действия переменная с тем же именем (см. пример ниже).
— При помощи необязательного аргумента PARENT_SCOPE
указывается, что следует осуществлять присваивание пере­менной родительской области действия.
Команда unset() позволяет удалить информацию о задан­ной переменной (CMake или окружения), т. е. вернуться к состо­янию до первого её присваивания. Как и для предыдущей ко­манды, необязательные аргументы CACHE и PARENT_SCOPE поз­воляют указать, к какой области действия следует применить команду.
Команда option() аналогична команде set() с аргумен­тами CACHE BOOL. По умолчанию переменной устанавливается значение OFF.
Замечание: так как кэш представляет собой отдельную область действия переменных, в нём могут храниться переменные с те-
116
2.7. Команды обработки данных
ми же именами, что и у переменных других областей. При этом такие переменные с одним именем будут разными.
ПРИМЕР
set(VALUE "value 1" CACHE STRING "Test value" FORCE)
set(VALUE "value 2")
message(${VALUE})
unset(VALUE)
message(${VALUE})
При исполнении этого фрагмента на печать будут выведе-
ны следующие строки:
value 2
N
value 1
Этот вывод демонстрирует принцип поиска перемен­ных в различных областях действия (п. 2.2.3). Первая коман­да message() обращается к переменной в текущей области действия. После удаления этой переменной вторая команда message() уже обращается к переменной кэша.
Однако если в этот фрагмент внести небольшое измене­ние:
set(VALUE "value 1")
set(VALUE "value 2" CACHE STRING "Test value" FORCE)
message(${VALUE})
unset(VALUE)
message(${VALUE})
117
2. Основы языка CMake
то в этом случае вывод инструмента CMake будет уже следую­щим:
value 2
value 2
Такой вывод происходит потому, что, как было отмечено выше, вторая команда set() удаляет из текущей области пере­менную с тем же именем. При этом команда unset() попытает­ся удалить информацию об уже не существующей переменной текущей области. ∗

2.7.2. math()

math(EXPR hимя_переменнойi hвыражениеi)
hвыражениеi :=
hцелочисленный_литералi
(hвыражениеi)
hвыражениеi hоперацияi hвыражениеi
hцелочисленный_литералi :=
hцифраi...hцифраi
 
 
hоперацияi :=
+
Эта команда позволяет вычислить арифметическое выра­жение и присвоить строковое представление его результата за-
118
-
  
*
  
/
  
%
  
|
  
&
  
^
  
~
  
<<
 
>>
2.7. Команды обработки данных
данной переменной. Поддерживаются целочисленные операн­ды и бинарные операции, аналогичные языку C.
Замечания:
— Так как унарные операции командой не поддерживают-
ся, выражения вида "-4 + 1" являются неправильными с её точки зрения. Для представления отрицательных чи­сел следует вычитать положительные литералы из нуля.
— При использовании пробелов внутри выражения его необ-
ходимо заключать в кавычки.
N

2.7.3. list()

Команда list() реализует основные алгоритмы работы со списками. Команда введена для удобства: её использование необязательно, все задачи, которые она выполняет, можно ре­ализовать другими средствами. Однако для сокращения исход­ного текста описания проектов и для придания ему большей яс­ности рекомендуется использовать эту команду там, где это воз­можно.
Так же как и команда set() (п. 2.7.1), команда list() мо­жет создавать новые переменные. Однако она создаёт их все­гда в текущей области действия (п. 2.2.3), в отличие от ко­манды set(), для которой можно указать аргументы CACHE или PARENT_SCOPE. Таким образом, новый список создаётся в те­кущей области действия, даже если исходный список находится в другой области. Чтобы скопировать полученное значение в ис­ходную область, можно использовать команду set().
119
2. Основы языка CMake
ПРИМЕР
function(test)
list(APPEND TEST_LIST d e f)
set(TEST_LIST ${TEST_LIST} PARENT_SCOPE)
endfunction()
set(TEST_LIST a b c)
test()
message("${TEST_LIST}")
Этот фрагмент кода выведет на печать «a;b;c;d;e;f». Сна­чала в нём определяется команда test() при помощи команд function()/endfunction() (п. 2.8.4). Далее команда set() при­сваивает значение переменной TEST_LIST. После этого испол­няется команда test(), которая добавляет в конец списка три значения. В результате создаётся переменная с тем же именем TEST_LIST, но уже в области действия функции. Чтобы скопиро­вать значение этой переменной в исходную область действия, используется команда set() с аргументом PARENT_SCOPE. ∗
При обращении к элементам списков можно использовать неотрицательные индексы 0, 1, 2, . . . для обращения к первому, второму и т. д. элементу с начала или −1, −2, −3, . . . для обраще­ния к первому, второму и т. д. с конца.
Замечание: при передаче командам значений индексов вне диа- пазона элементов списка выводится сообщение об ошибке. Вы­полнение команд продолжается, но генерирование файлов ко-
120
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]