Sign in Join
Wiki copytemporary

Macros and Conditionals/ru: what changed

Revision 1 to 2. 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-<figure>
1413<img src="conditional.png" title="conditional.png" width="600" />
15-<figcaption>conditional.png</figcaption>
16-</figure>
1714
1815Макросы сборки и условные определения существуют с Lazarus 0.9.29.
1916
20-<figure>
21-<img src="CompilerAdditionsAndOverrides1.png" title="CompilerAdditionsAndOverrides1.png" />
22-<figcaption>CompilerAdditionsAndOverrides1.png</figcaption>
23-</figure>
17+![](/wiki-images/c/cd/CompilerAdditionsAndOverrides1.png)
2418
2519# Условные определения
2620
2721В условных определениях используется простой язык сценариев.
2822
2923## Изменение параметров компилятора с помощью условных определений
3024
3125Сценарий условных определений может задавать некоторые переменные, значения которых используются IDE для параметров компилятора:
3226
3327- **UnitPath**: добавляется к *Other Source Files (-Fu)*. Символы `/` и `\` автоматически преобразуются в разделитель текущего пути. После добавления пути поиска с точкой с запятой макросы заменяются, а относительные пути расширяются каталогом пакета/проекта.
3428- **IncPath**: добавляется к *Include Files (-Fi)*.
3529- **LibraryPath**: добавляется к *Libraries (-Fl)*.
3630- **SrcPath**: добавляется к *Other sources (не используются компилятором, только IDE)*.
3731- **DebugPath**: добавляется к *Debugger path addition (не используется ни компилятором, ни инструментами кода, используется только отладчиком)*.
3832- **LinkerOptions**: добавляется к параметрам компоновщика (-k). Разделители путей не меняются. Относительные пути не расширяются. Макросы заменяются.
3933- **CustomOptions**: добавляется к параметрам компилятора. Разделители путей не меняются. Относительные пути не расширяются. Макросы заменяются.
4034- **OutputDir**: если задано, он заменит текущий каталог вывода. Разделители путей не меняются. Относительные пути не расширяются. Макросы заменяются.
4135
4236Для пакетов существует больше переменных для параметров использования. Эти пути наследуются, то есть добавляются ко всем пакетам/проектам, использующим этот пакет, прямо или косвенно:
4337
4438- **UsageUnitPath**: добавляется к используемым путям *Unit (-Fu)*. Символы `/` и `\` автоматически конвертиуются в текущий разделитель путей. После добавления пути поиска с точкой с запятой макросы заменяются, а относительные пути расширяются каталогом пакета/проекта.
4539- **UsageIncPath**: добавляется к используемым путям *Include (-Fi)*.
4640- **UsageLibraryPath**: добавляется к используемым путям *Library (-Fl)*.
4741- **UsageSrcPath**: добавляется к используемым путям *Source (не используются компилятором, только IDE)*.
4842- **UsageDebugPath**: добавляется к используемым путям *Debugger (не используется ни компилятором, ни инструментами кода, используется только отладчиком)*.
4943- **UsageLinkerOptions**: добавляется к используемым параметрам компоновщика (-k). Разделители путей не меняются. Относительные пути не расширяются. Макросы заменяются.
5044- **UsageCustomOptions**: добавляется к используемым параметрам компилятора. Разделители путей не меняются. Относительные пути не расширяются.
5145
5246## Синтаксис условных определений
5347
5448### Поддерживаемые синтактические конструкции
5549
5650- If \<условие\> then \<выражение\>;
5751- If \<условие\> then \<выражение\> else \<выражение\>;
5852- begin \<выражение\>; ... \<выражение\>; end;
5953- \<Переменная\>:=\<условие\>;
6054- \<Переменная\>+=\<условие\>;
6155- \<Комментарий\> //, { }, (* *)
6256- Пробелы, табуляции и переводы строк то же самое. Как и в Паскале, они нужны только для разделения двух идентификаторов/ключевых слов.
6357
6458### Переменные
6559
6660Переменные задаются просто путем присвоения значения. Есть несколько предопределенных переменных. См. список ниже.
6761
6862Переменные могут быть определены или не определены:
6963
7064``` pascal
7165if defined(Name) then ...
7266if undefined(Name) then ...
7367undefine(Name);
7468```
7569
7670Если переменная задана, она имеет один из трех типов:
7771
7872- none
7973- string
8074- number (int64)
8175
8276Переменная является **false**, если она имеет номер 0 или строку '0'. В противном случае это **true**. Это означает, что переменная без значения истинна и неопределенная переменная также истинна.
8377
8478Вы можете изменить тип переменной с помощью:
8579
8680``` pascal
8781a := '1'; // строка
8882a := integer(a); // преобразование в число с помощью StrToInt(), в случае неудачи 'a' остается строкой
8983a := int64(a); // преобразование в число с помощью StrToInt6(), в случае неудачи 'a' остается строкой
9084a := string(a); // преобразование в строку
9185```
9286
9387### Константы
9488
9589``` pascal
9690a := 1234; // десятичная
9791a := $A1B; // шестнадцатеричная
9892a := &127; // восьмеричная
9993a := %101; // двоичная
10094a := '10'; // строковая
10195a := #123; // символьная
10296```
10397
10498### Операторы
10599
106100- **+**: Два числа складываются, иначе они рассматриваются как строки и объединяются.
107101- **\<**, **\>**, **\<=**, **\>=**, **=**, **\<\>**: Два числа сравниваются математически, в противном случае они рассматриваются как строки и сравниваются лексикографически (с учетом регистра).
108102- **not**: Унарный (с изменением знака) логический оператор
109103- **and**, **or**, **xor**: Логические операторы
110104- **(**,**)**: Групповые операторы
111105- **:=**: Присвоение. Не допускается в выражениях.
112106- **+=**: Добавление и назначение. Не допускается в выражениях.
113107
114108Уровни приоритета:
115109
116110- 1 Not и унарный минус
117111- 1 And
118112- 2 Or
119113- 2 XOr
120114- 2 +
121115- 4 =
122116- 4 \<\>
123117- 4 \<
124118- 4 \<=
125119- 4 \>
126120- 4 \>=
127121
128122## Предопределенные переменные
129123
130124Перед запуском условного сценария среда IDE инициализирует несколько переменных:
131125
132126- **TargetOS**: целевая операционная система проекта, определенная fpc. например 'linux', 'win32', 'darwin', 'freebsd', 'wince'.
133127- **TargetCPU**: целевой процессор проекта, определенный fpc. например 'i386', 'x86_64', 'arm'
134128- **SrcOS**: значение 'win' для всех платформ MS Windows и 'unix' для всех unix-подобных платформ. Значение зависит от TargetOS.
135129- **SrcOS2**: значение 'bsd' для всех платформ, подобных BSD. Значение зависит от TargetOS.
136130- **True**: значение 1
137131- **False**: значение 0
138132- все макросы сборки, определенные в текущем проекте.
139133- все макросы сборки, определенные используемыми пакетами. Это означает, что если в проекте не определено значение для макроса пакета, будет использоваться значение условных операторов используемого пакета.
140134
141135## Предопределенные функции
142136
143137- **Defined(Variable)**: возвращает 1 (истина), если переменная определена, иначе 0 (ложь). Пример, `if Defined(Macro1) then ;`
144138- **Undefine(Variable)**: отменяет определение переменной. Пример: `Undefine(A);`
145139- **Int64(expression)**: возвращает значение выражения int64. Пример: `i:=int64('3');`
146140- **Integer(expression)**: возвращает целочисленное значение выражения. Пример: `i:=integer('3');`
147141- **String(expression)**: возвращает строковое значение выражения. Пример: `s:=string(3);`
148142- **GetIDEValue(string)**: См. [[IDE Macros in paths and filenames/ru|IDE macros]]
149143 - GetIDEValue('OS'): возвращает ОС, с которой была скомпилирована IDE (начиная с 1.0).
150144 - GetIDEValue('CPU'): возвращает процессор, с которым была скомпилирована IDE (начиная с 1.0).
151145 - GetIDEValue('SrcOS'): SrcOS IDE (начиная с 1.0).
152146 - GetIDEValue('SrcOS2'): SrcOS2 IDE (начиная с 1.0).
153147 - GetIDEValue('LCLWidgeType'): платформа LCL среды IDE, которая может отличаться от проекта. lazbuild возвращает win32, carbon или gtk2 в зависимости от ОС (начиная с 1.0).
154148- **GetEnv(string)**: возвращает переменную среды. Например, GetEnv('HOME') возвращает в Linux домашний каталог пользователя (начиная с 1.0).
155149- **GetProjValue(string)**: возвращает значение проекта.
156150 - GetProjValue('FPC_FULLVERSION'): возвращает FPC_FULLVERSION, полученный из компилятора проекта. Версия является целым числом, например 20701 (начиная с 1.3).
157151
158152# Порядок вычисления макроса
159153
1601541. берутся значения текущего проекта
1611552. если в проекте не определены значения для TargetOS, TargetCPU, IDE устанавливает значения по умолчанию
1621563. SrcOS и SrcOS2 вычисляются из TargetOS
1631574. вычисляются условные выражения используемых пакетов. Если пакет A использует пакет B, то условные выражения B вычисляются перед условными операторами A.
1641585. Каждый условный сценарий начинается со значений проекта.
165159 - Если проект не определяет значение для макроса пакета, используется результат используемого пакета.
166160 - Сценарий может изменять любой макрос во время выполнения, но используются только макросы сборки и встроенные макросы. Например, вы можете установить для TargetOS другое значение, но это не повлияет ни на какой другой сценарий, ни на какой путь поиска с использованием \$(TargetOS), даже на путь поиска самого пакета.
167161 - Если два пакета определяют один и тот же макрос сборки, то оба могут изменять значение (если только проект не устанавливает значение). Точный эффект зависит от порядка зависимости.
1681626. Макросы IDE по умолчанию используются последними.
169163
170164# Примеры
171165
172166## Добавление флага компилятора для цели Linux
173167
174168``` pascal
175169if TargetOS = 'linux' then
176170 CustomOptions := '-dUseCThreads';
177171```
178172
179173Примечание:
180174
181175- TargetOS - это предопределенный макрос IDE.
182176- CustomOptions - это результирующая переменная, используемая IDE.
183177- Идентификаторы нечувствительны к регистру, а оператор **=**(равно) - нет. Макрос TargetOS использует тот же регистр, что и компилятор, но в настоящее время все в нижнем регистре.
184178- IDE автоматически добавляет первое пространство при добавлении пользовательских параметров.
185179- При использовании в пакете вышеуказанное будет применяться только к параметрам, используемым для компиляции пакета, но не к проекту, использующему пакет.
186180
187181## Добавление некоторых параметров компоновщика для цели Mac OS X
188182
189183Компилятор использует для *Mac OS X* значение 'darwin' для *TargetOS*.
190184
191185``` pascal
192186if TargetOS = 'darwin' then begin
193187 LinkerOptions += ' -framework Cocoa';
194188 if TargetCPU = 'i386' then
195189 LinkerOptions += ' -framework OpenGL';
196190end;
197191```
198192
199193Примечание:
200194
201195- TargetOS и TargetCPU - это предопределенные в среде IDE макросы.
202196- Оператор **+=** добавляет строку или число.
203197- При добавлении нескольких опций вы должны добавить пробел между опциями.
204198- IDE автоматически добавляет первое пространство при добавлении параметров компоновщика.
205199- Вы можете вложить **begin**..**end** точно так же, как в Паскаль.
206200- Если выполняются оба условия, **LinkerOptions** будет содержать значение ' -framework Cocoa -framework OpenGL'.
207201- Среда IDE автоматически добавляет параметр -k при передаче параметров компоновщика компилятору.
208202- Вышеуказанное работает только для условных выражений проекта.
209203
210204## Добавление некоторых параметров компоновщика для Mac OS X для всех проектов с использованием пакета
211205
212206Пакеты имеют два разных набора опций. Набор, используемый для компиляции самого пакета, и параметры, добавленные ко всем проектам/пакетам, использующим пакет. Вам необходимо изменить параметр **usage** пакета:
213207
214208``` pascal
215209if TargetOS = 'darwin' then begin
216210 UsageLinkerOptions += ' -framework Cocoa';
217211 if TargetCPU = 'i386' then
218212 UsageLinkerOptions += ' -framework OpenGL';
219213end;
220214```
221215
222216## Добавление опции в пакет
223217
224218Если ваш пакет предоставляет некоторые дополнительные части, например возможность использовать opengl, вы можете определить макрос сборки. Далее объясняется, как это настроить шаг за шагом:
225219
226220Допустим, ваш пакет называется *Pkg1* и позволяет включить поддержку opengl, скомпилировав его с флагом **-dEnableOpenGL**. В пакете должен быть логический параметр **Pkg1_UseOpenGL** со значениями 'True' и 'False'.
227221
228222Откройте редактор пакетов 'pkg1', нажмите *compiler options* (Параметры компилятора), выберите страницу *IDE Macros* (Макросы IDE).
229223
230224Нажмите кнопку слева **+**, чтобы добавить новый макрос. Он будет называться 'Pkg1_Macro1'. Щелкните узел дерева, чтобы переименовать его в 'Pkg1_UseOpenGL'.
231225
232226Нажмите среднюю кнопку **+**, чтобы добавить новое значение макроса. Он будет называться 'Value1'. Щелкните узел дерева, чтобы переименовать его в 'True'. Повторите это для значения 'False'.
233227
234228Добавьте следующий код в текстовое поле Conditionals (Compiler Options / Other / Conditionals):
235229
236230``` pascal
237231if Pkg1_UseOpenGL = 'True' then
238232 CustomOptions := '-dEnableOpenGL';
239233```
240234
241-<figure>
242-<img src="Compileroptions_buildmacro_example1.png" title="Compileroptions_buildmacro_example1.png" />
243-<figcaption>Compileroptions_buildmacro_example1.png</figcaption>
244-</figure>
235+![](/wiki-images/c/c2/Compileroptions_buildmacro_example1.png)
245236
246237Примечание:
247238
248239- Значение 'True' чувствительно к регистру. Поскольку значение обычно выбирается из поля со списком, вероятность опечаток отсутствует.
249240- Если пользователь не установил никакого значения для макроса, переменная 'Pkg1_UseOpenGL' не определена, а результат выражения - 'false'.
250241
251242## Добавление режима release/debug
252243
253244### Режим release/debug для вашего проекта и всех ваших пакетов
254245
255246Примечание: для этого требуется Lazarus 0.9.31 или выше.
256247
257248В параметрах компилятора проекта (Project / Project Options / Compiler Options / Build modes) добавьте режим сборки *Release*. Добавление этого режима сборки автоматически активирует его, поэтому все изменения параметров компилятора теперь выполняются только в этом режиме сборки.
258249
259250В "Set Macro Values" (Установить значения макроса) щелкните левый столбец в последней строке "(none)". Установите его в "MyPackageOptions". Примечание: его нет в поле со списком.
260251
261252Установите его значение в опции. Например, "-O3".
262253
263-<figure>
264-<img src="Build_mode_release_macro1.png" title="Build_mode_release_macro1.png" />
265-<figcaption>Build_mode_release_macro1.png</figcaption>
266-</figure>
254+![](/wiki-images/1/1f/Build_mode_release_macro1.png)
267255
268256Этот макрос можно использовать в параметрах компилятора проекта и во всех пакетах.
269257
270258Для каждого пакета выполните: Откройте параметры компилятора пакета, перейдите на страницу *Other*. Добавьте в *Custom options* текст \$(MyPackageOptions).
271259
272260### Специальный режим release/debug для одного пакета
273261
274262Допустим, нормальный режим - это режим debug, и вам нужен другой режим для release.
275263
276264Откройте редактор пакетов 'pkg1', нажмите *compiler options*, выберите страницу *Build Macros*.
277265
278266В разделе *Build macros* нажмите кнопку слева **+**, чтобы добавить новый макрос. Он будет называться 'Pkg1_Macro1'. Щелкните узел дерева, чтобы переименовать его в 'Pkg1_Release'.
279267
280268Нажмите среднюю кнопку **+**, чтобы добавить новое *значение* макроса. Он будет называться 'Value1'. Щелкните узел дерева, чтобы переименовать его в 'True'. Повторите это для значения 'False'.
281269
282270Добавьте следующий код в текстовое поле Conditionals:
283271
284272``` pascal
285273if Pkg1_Release = 'True' then
286274 // режим release
287275 CustomOptions := '-O3'
288276else
289277 // режим debug
290278 CustomOptions := '-Sa Ctroi';
291279```
292280
293281Примечание:
294282
295283- Значение 'True' чувствительно к регистру. Поскольку значение обычно выбирается из поля со списком, вероятность опечаток отсутствует.
296284- Если пользователь не установил никакого значения для макроса, переменная 'Pkg1_Release' не определена, а результат выражения - false.
297285
298286## Добавление макроса для путей поиска для работы с разными платформами
299287
300288Допустим, ваш пакет называется *Pkg1* и использует Windows GDI в MS Windows и X11 в Linux и BSD. Независимые от платформы модули находятся в основном каталоге пакета, и вы создали два подкаталога 'gdi' и 'x11', содержащие зависящие от платформы модули:
301289
302290``` bash
303291/path/of/your/package/pkg1/
304292 pkg1.lpk
305293 pkg1.pas
306294 generalunit.pas
307295 gdi/
308296 backend.pas
309297 x11/
310298 backend.pas
311299```
312300
313301Модуль *backend* в *gdi* следует использовать в Win32, Win64 и WinCE, а в Linux и FreeBSD следует использовать модуль *backend* в *x11*. Это означает, что путь поиска *Other unit files (-Fu)* (Другие файлы модулей (-Fu)) должен быть адаптирован в зависимости от целевой ОС. Ниже описывается, как настроить это шаг за шагом:
314302
315303Откройте редактор пакетов 'pkg1', щелкните параметры компилятора, выберите страницу *Build Macros* (Сборка макросов).
316304
317305Нажмите кнопку слева **+**, чтобы добавить новый макрос. Он будет называться 'Pkg1_Macro1'. Щелкните узел дерева, чтобы переименовать его в 'Pkg1_Backend'.
318306
319307Нажмите среднюю кнопку **+**, чтобы добавить новое значение макроса. Он будет называться 'Value1'. Щелкните узел дерева, чтобы переименовать его в 'gdi'. Повторите это для значения 'x11'.
320308
321309Добавьте следующий код в текстовое поле Conditionals:
322310
323311``` pascal
324312// выбираем значение для Pkg1_Backend в зависимости от TargetOS
325313if undefined(Pkg1_Backend) then begin
326314 if SrcOS='win' then
327315 Pkg1_Backend:='gdi'
328316 else
329317 Pkg1_Backend:='x11';
330318end;
331319```
332320
333321Макрос **\$(Pkg1_Backend)** станет доступным после нажатия кнопки ОК. Итак, нажмите 'Ok', чтобы закрыть параметры компилятора, и откройте его снова, чтобы использовать его в пути поиска *Other unit files (-Fu)* (Другие файлы модулей (-Fu)).
334322
335-<figure>
336-<img src="Compileroptions_buildmacro_example2.png" title="Compileroptions_buildmacro_example2.png" />
337-<figcaption>Compileroptions_buildmacro_example2.png</figcaption>
338-</figure>
323+![](/wiki-images/7/70/Compileroptions_buildmacro_example2.png)
339324
340325Примечание:
341326
342327- Пользователь может изменить значение Pkg1_Backend. Поэтому рекомендуется заключить настройку в *if undefined(Pkg1_Backend)*.
343328- Вместо макроса SrcOS вы можете использовать `if (TargetOS='win32') or (TargetOS='win64') or (TargetOS='wince') then ...`
344329
345330---
346331*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