Sign in Join
Wiki copytemporary

Macros and Conditionals/ru: what changed

Revision 2 to 3. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11# Обзор
22
33Макросы можно использовать в путях поиска и именах файлов, чтобы IDE автоматически адаптировала их к целевой платформе.
44
55**Build macros** (Макросы сборки) - это макросы, специфичные для проекта/пакета. Они **не** передаются компилятору. Ярким примером является **LCLWidgetType**, который определяется пакетом *LCL* и позволяет выбирать набор виджетов (carbon, gtk, qt, win32, wince, ...).
66
77**Conditionals** (Условные определения) - это правила, позволяющие задавать макросы в зависимости от целевой платформы и/или других макросов. Например, вы можете использовать их для определения специальных параметров компоновщика при компиляции для Mac OS X. Они используют язык сценариев типа паскаль, позволяющий определять даже сложные правила.
88
99Вы можете задать макросы сборки через [[IDE Window: Compiler Options/ru|Project / Project Options / Compiler Options / Additions and Overrides]].
1010
1111Вы можете задать условные определения через Project / Project Options / Compiler Options / Other / Conditionals (прим.перев.: в версиях Лазаруса 2.0.х и выше опция находится здесь Project / Project Options / Compiler Options / Custom Options).
1212
13-<img src="conditional.png" title="conditional.png" width="600" />
13+![](/wiki-images/3/39/Conditional.png)
1414
1515Макросы сборки и условные определения существуют с Lazarus 0.9.29.
1616
1717![](/wiki-images/c/cd/CompilerAdditionsAndOverrides1.png)
1818
1919# Условные определения
2020
2121В условных определениях используется простой язык сценариев.
2222
2323## Изменение параметров компилятора с помощью условных определений
2424
2525Сценарий условных определений может задавать некоторые переменные, значения которых используются IDE для параметров компилятора:
2626
2727- **UnitPath**: добавляется к *Other Source Files (-Fu)*. Символы `/` и `\` автоматически преобразуются в разделитель текущего пути. После добавления пути поиска с точкой с запятой макросы заменяются, а относительные пути расширяются каталогом пакета/проекта.
2828- **IncPath**: добавляется к *Include Files (-Fi)*.
2929- **LibraryPath**: добавляется к *Libraries (-Fl)*.
3030- **SrcPath**: добавляется к *Other sources (не используются компилятором, только IDE)*.
3131- **DebugPath**: добавляется к *Debugger path addition (не используется ни компилятором, ни инструментами кода, используется только отладчиком)*.
3232- **LinkerOptions**: добавляется к параметрам компоновщика (-k). Разделители путей не меняются. Относительные пути не расширяются. Макросы заменяются.
3333- **CustomOptions**: добавляется к параметрам компилятора. Разделители путей не меняются. Относительные пути не расширяются. Макросы заменяются.
3434- **OutputDir**: если задано, он заменит текущий каталог вывода. Разделители путей не меняются. Относительные пути не расширяются. Макросы заменяются.
3535
3636Для пакетов существует больше переменных для параметров использования. Эти пути наследуются, то есть добавляются ко всем пакетам/проектам, использующим этот пакет, прямо или косвенно:
3737
3838- **UsageUnitPath**: добавляется к используемым путям *Unit (-Fu)*. Символы `/` и `\` автоматически конвертиуются в текущий разделитель путей. После добавления пути поиска с точкой с запятой макросы заменяются, а относительные пути расширяются каталогом пакета/проекта.
3939- **UsageIncPath**: добавляется к используемым путям *Include (-Fi)*.
4040- **UsageLibraryPath**: добавляется к используемым путям *Library (-Fl)*.
4141- **UsageSrcPath**: добавляется к используемым путям *Source (не используются компилятором, только IDE)*.
4242- **UsageDebugPath**: добавляется к используемым путям *Debugger (не используется ни компилятором, ни инструментами кода, используется только отладчиком)*.
4343- **UsageLinkerOptions**: добавляется к используемым параметрам компоновщика (-k). Разделители путей не меняются. Относительные пути не расширяются. Макросы заменяются.
4444- **UsageCustomOptions**: добавляется к используемым параметрам компилятора. Разделители путей не меняются. Относительные пути не расширяются.
4545
4646## Синтаксис условных определений
4747
4848### Поддерживаемые синтактические конструкции
4949
5050- If \<условие\> then \<выражение\>;
5151- If \<условие\> then \<выражение\> else \<выражение\>;
5252- begin \<выражение\>; ... \<выражение\>; end;
5353- \<Переменная\>:=\<условие\>;
5454- \<Переменная\>+=\<условие\>;
5555- \<Комментарий\> //, { }, (* *)
5656- Пробелы, табуляции и переводы строк то же самое. Как и в Паскале, они нужны только для разделения двух идентификаторов/ключевых слов.
5757
5858### Переменные
5959
6060Переменные задаются просто путем присвоения значения. Есть несколько предопределенных переменных. См. список ниже.
6161
6262Переменные могут быть определены или не определены:
6363
6464``` pascal
6565if defined(Name) then ...
6666if undefined(Name) then ...
6767undefine(Name);
6868```
6969
7070Если переменная задана, она имеет один из трех типов:
7171
7272- none
7373- string
7474- number (int64)
7575
7676Переменная является **false**, если она имеет номер 0 или строку '0'. В противном случае это **true**. Это означает, что переменная без значения истинна и неопределенная переменная также истинна.
7777
7878Вы можете изменить тип переменной с помощью:
7979
8080``` pascal
8181a := '1'; // строка
8282a := integer(a); // преобразование в число с помощью StrToInt(), в случае неудачи 'a' остается строкой
8383a := int64(a); // преобразование в число с помощью StrToInt6(), в случае неудачи 'a' остается строкой
8484a := string(a); // преобразование в строку
8585```
8686
8787### Константы
8888
8989``` pascal
9090a := 1234; // десятичная
9191a := $A1B; // шестнадцатеричная
9292a := &127; // восьмеричная
9393a := %101; // двоичная
9494a := '10'; // строковая
9595a := #123; // символьная
9696```
9797
9898### Операторы
9999
100100- **+**: Два числа складываются, иначе они рассматриваются как строки и объединяются.
101101- **\<**, **\>**, **\<=**, **\>=**, **=**, **\<\>**: Два числа сравниваются математически, в противном случае они рассматриваются как строки и сравниваются лексикографически (с учетом регистра).
102102- **not**: Унарный (с изменением знака) логический оператор
103103- **and**, **or**, **xor**: Логические операторы
104104- **(**,**)**: Групповые операторы
105105- **:=**: Присвоение. Не допускается в выражениях.
106106- **+=**: Добавление и назначение. Не допускается в выражениях.
107107
108108Уровни приоритета:
109109
110110- 1 Not и унарный минус
111111- 1 And
112112- 2 Or
113113- 2 XOr
114114- 2 +
115115- 4 =
116116- 4 \<\>
117117- 4 \<
118118- 4 \<=
119119- 4 \>
120120- 4 \>=
121121
122122## Предопределенные переменные
123123
124124Перед запуском условного сценария среда IDE инициализирует несколько переменных:
125125
126126- **TargetOS**: целевая операционная система проекта, определенная fpc. например 'linux', 'win32', 'darwin', 'freebsd', 'wince'.
127127- **TargetCPU**: целевой процессор проекта, определенный fpc. например 'i386', 'x86_64', 'arm'
128128- **SrcOS**: значение 'win' для всех платформ MS Windows и 'unix' для всех unix-подобных платформ. Значение зависит от TargetOS.
129129- **SrcOS2**: значение 'bsd' для всех платформ, подобных BSD. Значение зависит от TargetOS.
130130- **True**: значение 1
131131- **False**: значение 0
132132- все макросы сборки, определенные в текущем проекте.
133133- все макросы сборки, определенные используемыми пакетами. Это означает, что если в проекте не определено значение для макроса пакета, будет использоваться значение условных операторов используемого пакета.
134134
135135## Предопределенные функции
136136
137137- **Defined(Variable)**: возвращает 1 (истина), если переменная определена, иначе 0 (ложь). Пример, `if Defined(Macro1) then ;`
138138- **Undefine(Variable)**: отменяет определение переменной. Пример: `Undefine(A);`
139139- **Int64(expression)**: возвращает значение выражения int64. Пример: `i:=int64('3');`
140140- **Integer(expression)**: возвращает целочисленное значение выражения. Пример: `i:=integer('3');`
141141- **String(expression)**: возвращает строковое значение выражения. Пример: `s:=string(3);`
142142- **GetIDEValue(string)**: См. [[IDE Macros in paths and filenames/ru|IDE macros]]
143143 - GetIDEValue('OS'): возвращает ОС, с которой была скомпилирована IDE (начиная с 1.0).
144144 - GetIDEValue('CPU'): возвращает процессор, с которым была скомпилирована IDE (начиная с 1.0).
145145 - GetIDEValue('SrcOS'): SrcOS IDE (начиная с 1.0).
146146 - GetIDEValue('SrcOS2'): SrcOS2 IDE (начиная с 1.0).
147147 - GetIDEValue('LCLWidgeType'): платформа LCL среды IDE, которая может отличаться от проекта. lazbuild возвращает win32, carbon или gtk2 в зависимости от ОС (начиная с 1.0).
148148- **GetEnv(string)**: возвращает переменную среды. Например, GetEnv('HOME') возвращает в Linux домашний каталог пользователя (начиная с 1.0).
149149- **GetProjValue(string)**: возвращает значение проекта.
150150 - GetProjValue('FPC_FULLVERSION'): возвращает FPC_FULLVERSION, полученный из компилятора проекта. Версия является целым числом, например 20701 (начиная с 1.3).
151151
152152# Порядок вычисления макроса
153153
1541541. берутся значения текущего проекта
1551552. если в проекте не определены значения для TargetOS, TargetCPU, IDE устанавливает значения по умолчанию
1561563. SrcOS и SrcOS2 вычисляются из TargetOS
1571574. вычисляются условные выражения используемых пакетов. Если пакет A использует пакет B, то условные выражения B вычисляются перед условными операторами A.
1581585. Каждый условный сценарий начинается со значений проекта.
159159 - Если проект не определяет значение для макроса пакета, используется результат используемого пакета.
160160 - Сценарий может изменять любой макрос во время выполнения, но используются только макросы сборки и встроенные макросы. Например, вы можете установить для TargetOS другое значение, но это не повлияет ни на какой другой сценарий, ни на какой путь поиска с использованием \$(TargetOS), даже на путь поиска самого пакета.
161161 - Если два пакета определяют один и тот же макрос сборки, то оба могут изменять значение (если только проект не устанавливает значение). Точный эффект зависит от порядка зависимости.
1621626. Макросы IDE по умолчанию используются последними.
163163
164164# Примеры
165165
166166## Добавление флага компилятора для цели Linux
167167
168168``` pascal
169169if TargetOS = 'linux' then
170170 CustomOptions := '-dUseCThreads';
171171```
172172
173173Примечание:
174174
175175- TargetOS - это предопределенный макрос IDE.
176176- CustomOptions - это результирующая переменная, используемая IDE.
177177- Идентификаторы нечувствительны к регистру, а оператор **=**(равно) - нет. Макрос TargetOS использует тот же регистр, что и компилятор, но в настоящее время все в нижнем регистре.
178178- IDE автоматически добавляет первое пространство при добавлении пользовательских параметров.
179179- При использовании в пакете вышеуказанное будет применяться только к параметрам, используемым для компиляции пакета, но не к проекту, использующему пакет.
180180
181181## Добавление некоторых параметров компоновщика для цели Mac OS X
182182
183183Компилятор использует для *Mac OS X* значение 'darwin' для *TargetOS*.
184184
185185``` pascal
186186if TargetOS = 'darwin' then begin
187187 LinkerOptions += ' -framework Cocoa';
188188 if TargetCPU = 'i386' then
189189 LinkerOptions += ' -framework OpenGL';
190190end;
191191```
192192
193193Примечание:
194194
195195- TargetOS и TargetCPU - это предопределенные в среде IDE макросы.
196196- Оператор **+=** добавляет строку или число.
197197- При добавлении нескольких опций вы должны добавить пробел между опциями.
198198- IDE автоматически добавляет первое пространство при добавлении параметров компоновщика.
199199- Вы можете вложить **begin**..**end** точно так же, как в Паскаль.
200200- Если выполняются оба условия, **LinkerOptions** будет содержать значение ' -framework Cocoa -framework OpenGL'.
201201- Среда IDE автоматически добавляет параметр -k при передаче параметров компоновщика компилятору.
202202- Вышеуказанное работает только для условных выражений проекта.
203203
204204## Добавление некоторых параметров компоновщика для Mac OS X для всех проектов с использованием пакета
205205
206206Пакеты имеют два разных набора опций. Набор, используемый для компиляции самого пакета, и параметры, добавленные ко всем проектам/пакетам, использующим пакет. Вам необходимо изменить параметр **usage** пакета:
207207
208208``` pascal
209209if TargetOS = 'darwin' then begin
210210 UsageLinkerOptions += ' -framework Cocoa';
211211 if TargetCPU = 'i386' then
212212 UsageLinkerOptions += ' -framework OpenGL';
213213end;
214214```
215215
216216## Добавление опции в пакет
217217
218218Если ваш пакет предоставляет некоторые дополнительные части, например возможность использовать opengl, вы можете определить макрос сборки. Далее объясняется, как это настроить шаг за шагом:
219219
220220Допустим, ваш пакет называется *Pkg1* и позволяет включить поддержку opengl, скомпилировав его с флагом **-dEnableOpenGL**. В пакете должен быть логический параметр **Pkg1_UseOpenGL** со значениями 'True' и 'False'.
221221
222222Откройте редактор пакетов 'pkg1', нажмите *compiler options* (Параметры компилятора), выберите страницу *IDE Macros* (Макросы IDE).
223223
224224Нажмите кнопку слева **+**, чтобы добавить новый макрос. Он будет называться 'Pkg1_Macro1'. Щелкните узел дерева, чтобы переименовать его в 'Pkg1_UseOpenGL'.
225225
226226Нажмите среднюю кнопку **+**, чтобы добавить новое значение макроса. Он будет называться 'Value1'. Щелкните узел дерева, чтобы переименовать его в 'True'. Повторите это для значения 'False'.
227227
228228Добавьте следующий код в текстовое поле Conditionals (Compiler Options / Other / Conditionals):
229229
230230``` pascal
231231if Pkg1_UseOpenGL = 'True' then
232232 CustomOptions := '-dEnableOpenGL';
233233```
234234
235235![](/wiki-images/c/c2/Compileroptions_buildmacro_example1.png)
236236
237237Примечание:
238238
239239- Значение 'True' чувствительно к регистру. Поскольку значение обычно выбирается из поля со списком, вероятность опечаток отсутствует.
240240- Если пользователь не установил никакого значения для макроса, переменная 'Pkg1_UseOpenGL' не определена, а результат выражения - 'false'.
241241
242242## Добавление режима release/debug
243243
244244### Режим release/debug для вашего проекта и всех ваших пакетов
245245
246246Примечание: для этого требуется Lazarus 0.9.31 или выше.
247247
248248В параметрах компилятора проекта (Project / Project Options / Compiler Options / Build modes) добавьте режим сборки *Release*. Добавление этого режима сборки автоматически активирует его, поэтому все изменения параметров компилятора теперь выполняются только в этом режиме сборки.
249249
250250В "Set Macro Values" (Установить значения макроса) щелкните левый столбец в последней строке "(none)". Установите его в "MyPackageOptions". Примечание: его нет в поле со списком.
251251
252252Установите его значение в опции. Например, "-O3".
253253
254254![](/wiki-images/1/1f/Build_mode_release_macro1.png)
255255
256256Этот макрос можно использовать в параметрах компилятора проекта и во всех пакетах.
257257
258258Для каждого пакета выполните: Откройте параметры компилятора пакета, перейдите на страницу *Other*. Добавьте в *Custom options* текст \$(MyPackageOptions).
259259
260260### Специальный режим release/debug для одного пакета
261261
262262Допустим, нормальный режим - это режим debug, и вам нужен другой режим для release.
263263
264264Откройте редактор пакетов 'pkg1', нажмите *compiler options*, выберите страницу *Build Macros*.
265265
266266В разделе *Build macros* нажмите кнопку слева **+**, чтобы добавить новый макрос. Он будет называться 'Pkg1_Macro1'. Щелкните узел дерева, чтобы переименовать его в 'Pkg1_Release'.
267267
268268Нажмите среднюю кнопку **+**, чтобы добавить новое *значение* макроса. Он будет называться 'Value1'. Щелкните узел дерева, чтобы переименовать его в 'True'. Повторите это для значения 'False'.
269269
270270Добавьте следующий код в текстовое поле Conditionals:
271271
272272``` pascal
273273if Pkg1_Release = 'True' then
274274 // режим release
275275 CustomOptions := '-O3'
276276else
277277 // режим debug
278278 CustomOptions := '-Sa Ctroi';
279279```
280280
281281Примечание:
282282
283283- Значение 'True' чувствительно к регистру. Поскольку значение обычно выбирается из поля со списком, вероятность опечаток отсутствует.
284284- Если пользователь не установил никакого значения для макроса, переменная 'Pkg1_Release' не определена, а результат выражения - false.
285285
286286## Добавление макроса для путей поиска для работы с разными платформами
287287
288288Допустим, ваш пакет называется *Pkg1* и использует Windows GDI в MS Windows и X11 в Linux и BSD. Независимые от платформы модули находятся в основном каталоге пакета, и вы создали два подкаталога 'gdi' и 'x11', содержащие зависящие от платформы модули:
289289
290290``` bash
291291/path/of/your/package/pkg1/
292292 pkg1.lpk
293293 pkg1.pas
294294 generalunit.pas
295295 gdi/
296296 backend.pas
297297 x11/
298298 backend.pas
299299```
300300
301301Модуль *backend* в *gdi* следует использовать в Win32, Win64 и WinCE, а в Linux и FreeBSD следует использовать модуль *backend* в *x11*. Это означает, что путь поиска *Other unit files (-Fu)* (Другие файлы модулей (-Fu)) должен быть адаптирован в зависимости от целевой ОС. Ниже описывается, как настроить это шаг за шагом:
302302
303303Откройте редактор пакетов 'pkg1', щелкните параметры компилятора, выберите страницу *Build Macros* (Сборка макросов).
304304
305305Нажмите кнопку слева **+**, чтобы добавить новый макрос. Он будет называться 'Pkg1_Macro1'. Щелкните узел дерева, чтобы переименовать его в 'Pkg1_Backend'.
306306
307307Нажмите среднюю кнопку **+**, чтобы добавить новое значение макроса. Он будет называться 'Value1'. Щелкните узел дерева, чтобы переименовать его в 'gdi'. Повторите это для значения 'x11'.
308308
309309Добавьте следующий код в текстовое поле Conditionals:
310310
311311``` pascal
312312// выбираем значение для Pkg1_Backend в зависимости от TargetOS
313313if undefined(Pkg1_Backend) then begin
314314 if SrcOS='win' then
315315 Pkg1_Backend:='gdi'
316316 else
317317 Pkg1_Backend:='x11';
318318end;
319319```
320320
321321Макрос **\$(Pkg1_Backend)** станет доступным после нажатия кнопки ОК. Итак, нажмите 'Ok', чтобы закрыть параметры компилятора, и откройте его снова, чтобы использовать его в пути поиска *Other unit files (-Fu)* (Другие файлы модулей (-Fu)).
322322
323323![](/wiki-images/7/70/Compileroptions_buildmacro_example2.png)
324324
325325Примечание:
326326
327327- Пользователь может изменить значение Pkg1_Backend. Поэтому рекомендуется заключить настройку в *if undefined(Pkg1_Backend)*.
328328- Вместо макроса SrcOS вы можете использовать `if (TargetOS='win32') or (TargetOS='win64') or (TargetOS='wince') then ...`
329329
330330---
331331*From the Free Pascal wiki, page "Macros and Conditionals/ru", as it stood on 2021-01-24 after a change by Zoltanleo, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history