Sign in Join
Wiki copytemporary

Macros and Conditionals/ru: what changed

Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.

Title: Macros and Conditionals/ru

OldNewLine
1+# Обзор
2+
3+Макросы можно использовать в путях поиска и именах файлов, чтобы IDE автоматически адаптировала их к целевой платформе.
4+
5+**Build macros** (Макросы сборки) - это макросы, специфичные для проекта/пакета. Они **не** передаются компилятору. Ярким примером является **LCLWidgetType**, который определяется пакетом *LCL* и позволяет выбирать набор виджетов (carbon, gtk, qt, win32, wince, ...).
6+
7+**Conditionals** (Условные определения) - это правила, позволяющие задавать макросы в зависимости от целевой платформы и/или других макросов. Например, вы можете использовать их для определения специальных параметров компоновщика при компиляции для Mac OS X. Они используют язык сценариев типа паскаль, позволяющий определять даже сложные правила.
8+
9+Вы можете задать макросы сборки через [[IDE Window: Compiler Options/ru|Project / Project Options / Compiler Options / Additions and Overrides]].
10+
11+Вы можете задать условные определения через Project / Project Options / Compiler Options / Other / Conditionals (прим.перев.: в версиях Лазаруса 2.0.х и выше опция находится здесь Project / Project Options / Compiler Options / Custom Options).
12+
13+<figure>
14+<img src="conditional.png" title="conditional.png" width="600" />
15+<figcaption>conditional.png</figcaption>
16+</figure>
17+
18+Макросы сборки и условные определения существуют с Lazarus 0.9.29.
19+
20+<figure>
21+<img src="CompilerAdditionsAndOverrides1.png" title="CompilerAdditionsAndOverrides1.png" />
22+<figcaption>CompilerAdditionsAndOverrides1.png</figcaption>
23+</figure>
24+
25+# Условные определения
26+
27+В условных определениях используется простой язык сценариев.
28+
29+## Изменение параметров компилятора с помощью условных определений
30+
31+Сценарий условных определений может задавать некоторые переменные, значения которых используются IDE для параметров компилятора:
32+
33+- **UnitPath**: добавляется к *Other Source Files (-Fu)*. Символы `/` и `\` автоматически преобразуются в разделитель текущего пути. После добавления пути поиска с точкой с запятой макросы заменяются, а относительные пути расширяются каталогом пакета/проекта.
34+- **IncPath**: добавляется к *Include Files (-Fi)*.
35+- **LibraryPath**: добавляется к *Libraries (-Fl)*.
36+- **SrcPath**: добавляется к *Other sources (не используются компилятором, только IDE)*.
37+- **DebugPath**: добавляется к *Debugger path addition (не используется ни компилятором, ни инструментами кода, используется только отладчиком)*.
38+- **LinkerOptions**: добавляется к параметрам компоновщика (-k). Разделители путей не меняются. Относительные пути не расширяются. Макросы заменяются.
39+- **CustomOptions**: добавляется к параметрам компилятора. Разделители путей не меняются. Относительные пути не расширяются. Макросы заменяются.
40+- **OutputDir**: если задано, он заменит текущий каталог вывода. Разделители путей не меняются. Относительные пути не расширяются. Макросы заменяются.
41+
42+Для пакетов существует больше переменных для параметров использования. Эти пути наследуются, то есть добавляются ко всем пакетам/проектам, использующим этот пакет, прямо или косвенно:
43+
44+- **UsageUnitPath**: добавляется к используемым путям *Unit (-Fu)*. Символы `/` и `\` автоматически конвертиуются в текущий разделитель путей. После добавления пути поиска с точкой с запятой макросы заменяются, а относительные пути расширяются каталогом пакета/проекта.
45+- **UsageIncPath**: добавляется к используемым путям *Include (-Fi)*.
46+- **UsageLibraryPath**: добавляется к используемым путям *Library (-Fl)*.
47+- **UsageSrcPath**: добавляется к используемым путям *Source (не используются компилятором, только IDE)*.
48+- **UsageDebugPath**: добавляется к используемым путям *Debugger (не используется ни компилятором, ни инструментами кода, используется только отладчиком)*.
49+- **UsageLinkerOptions**: добавляется к используемым параметрам компоновщика (-k). Разделители путей не меняются. Относительные пути не расширяются. Макросы заменяются.
50+- **UsageCustomOptions**: добавляется к используемым параметрам компилятора. Разделители путей не меняются. Относительные пути не расширяются.
51+
52+## Синтаксис условных определений
53+
54+### Поддерживаемые синтактические конструкции
55+
56+- If \<условие\> then \<выражение\>;
57+- If \<условие\> then \<выражение\> else \<выражение\>;
58+- begin \<выражение\>; ... \<выражение\>; end;
59+- \<Переменная\>:=\<условие\>;
60+- \<Переменная\>+=\<условие\>;
61+- \<Комментарий\> //, { }, (* *)
62+- Пробелы, табуляции и переводы строк то же самое. Как и в Паскале, они нужны только для разделения двух идентификаторов/ключевых слов.
63+
64+### Переменные
65+
66+Переменные задаются просто путем присвоения значения. Есть несколько предопределенных переменных. См. список ниже.
67+
68+Переменные могут быть определены или не определены:
69+
70+``` pascal
71+if defined(Name) then ...
72+if undefined(Name) then ...
73+undefine(Name);
74+```
75+
76+Если переменная задана, она имеет один из трех типов:
77+
78+- none
79+- string
80+- number (int64)
81+
82+Переменная является **false**, если она имеет номер 0 или строку '0'. В противном случае это **true**. Это означает, что переменная без значения истинна и неопределенная переменная также истинна.
83+
84+Вы можете изменить тип переменной с помощью:
85+
86+``` pascal
87+a := '1'; // строка
88+a := integer(a); // преобразование в число с помощью StrToInt(), в случае неудачи 'a' остается строкой
89+a := int64(a); // преобразование в число с помощью StrToInt6(), в случае неудачи 'a' остается строкой
90+a := string(a); // преобразование в строку
91+```
92+
93+### Константы
94+
95+``` pascal
96+a := 1234; // десятичная
97+a := $A1B; // шестнадцатеричная
98+a := &127; // восьмеричная
99+a := %101; // двоичная
100+a := '10'; // строковая
101+a := #123; // символьная
102+```
103+
104+### Операторы
105+
106+- **+**: Два числа складываются, иначе они рассматриваются как строки и объединяются.
107+- **\<**, **\>**, **\<=**, **\>=**, **=**, **\<\>**: Два числа сравниваются математически, в противном случае они рассматриваются как строки и сравниваются лексикографически (с учетом регистра).
108+- **not**: Унарный (с изменением знака) логический оператор
109+- **and**, **or**, **xor**: Логические операторы
110+- **(**,**)**: Групповые операторы
111+- **:=**: Присвоение. Не допускается в выражениях.
112+- **+=**: Добавление и назначение. Не допускается в выражениях.
113+
114+Уровни приоритета:
115+
116+- 1 Not и унарный минус
117+- 1 And
118+- 2 Or
119+- 2 XOr
120+- 2 +
121+- 4 =
122+- 4 \<\>
123+- 4 \<
124+- 4 \<=
125+- 4 \>
126+- 4 \>=
127+
128+## Предопределенные переменные
129+
130+Перед запуском условного сценария среда IDE инициализирует несколько переменных:
131+
132+- **TargetOS**: целевая операционная система проекта, определенная fpc. например 'linux', 'win32', 'darwin', 'freebsd', 'wince'.
133+- **TargetCPU**: целевой процессор проекта, определенный fpc. например 'i386', 'x86_64', 'arm'
134+- **SrcOS**: значение 'win' для всех платформ MS Windows и 'unix' для всех unix-подобных платформ. Значение зависит от TargetOS.
135+- **SrcOS2**: значение 'bsd' для всех платформ, подобных BSD. Значение зависит от TargetOS.
136+- **True**: значение 1
137+- **False**: значение 0
138+- все макросы сборки, определенные в текущем проекте.
139+- все макросы сборки, определенные используемыми пакетами. Это означает, что если в проекте не определено значение для макроса пакета, будет использоваться значение условных операторов используемого пакета.
140+
141+## Предопределенные функции
142+
143+- **Defined(Variable)**: возвращает 1 (истина), если переменная определена, иначе 0 (ложь). Пример, `if Defined(Macro1) then ;`
144+- **Undefine(Variable)**: отменяет определение переменной. Пример: `Undefine(A);`
145+- **Int64(expression)**: возвращает значение выражения int64. Пример: `i:=int64('3');`
146+- **Integer(expression)**: возвращает целочисленное значение выражения. Пример: `i:=integer('3');`
147+- **String(expression)**: возвращает строковое значение выражения. Пример: `s:=string(3);`
148+- **GetIDEValue(string)**: См. [[IDE Macros in paths and filenames/ru|IDE macros]]
149+ - GetIDEValue('OS'): возвращает ОС, с которой была скомпилирована IDE (начиная с 1.0).
150+ - GetIDEValue('CPU'): возвращает процессор, с которым была скомпилирована IDE (начиная с 1.0).
151+ - GetIDEValue('SrcOS'): SrcOS IDE (начиная с 1.0).
152+ - GetIDEValue('SrcOS2'): SrcOS2 IDE (начиная с 1.0).
153+ - GetIDEValue('LCLWidgeType'): платформа LCL среды IDE, которая может отличаться от проекта. lazbuild возвращает win32, carbon или gtk2 в зависимости от ОС (начиная с 1.0).
154+- **GetEnv(string)**: возвращает переменную среды. Например, GetEnv('HOME') возвращает в Linux домашний каталог пользователя (начиная с 1.0).
155+- **GetProjValue(string)**: возвращает значение проекта.
156+ - GetProjValue('FPC_FULLVERSION'): возвращает FPC_FULLVERSION, полученный из компилятора проекта. Версия является целым числом, например 20701 (начиная с 1.3).
157+
158+# Порядок вычисления макроса
159+
160+1. берутся значения текущего проекта
161+2. если в проекте не определены значения для TargetOS, TargetCPU, IDE устанавливает значения по умолчанию
162+3. SrcOS и SrcOS2 вычисляются из TargetOS
163+4. вычисляются условные выражения используемых пакетов. Если пакет A использует пакет B, то условные выражения B вычисляются перед условными операторами A.
164+5. Каждый условный сценарий начинается со значений проекта.
165+ - Если проект не определяет значение для макроса пакета, используется результат используемого пакета.
166+ - Сценарий может изменять любой макрос во время выполнения, но используются только макросы сборки и встроенные макросы. Например, вы можете установить для TargetOS другое значение, но это не повлияет ни на какой другой сценарий, ни на какой путь поиска с использованием \$(TargetOS), даже на путь поиска самого пакета.
167+ - Если два пакета определяют один и тот же макрос сборки, то оба могут изменять значение (если только проект не устанавливает значение). Точный эффект зависит от порядка зависимости.
168+6. Макросы IDE по умолчанию используются последними.
169+
170+# Примеры
171+
172+## Добавление флага компилятора для цели Linux
173+
174+``` pascal
175+if TargetOS = 'linux' then
176+ CustomOptions := '-dUseCThreads';
177+```
178+
179+Примечание:
180+
181+- TargetOS - это предопределенный макрос IDE.
182+- CustomOptions - это результирующая переменная, используемая IDE.
183+- Идентификаторы нечувствительны к регистру, а оператор **=**(равно) - нет. Макрос TargetOS использует тот же регистр, что и компилятор, но в настоящее время все в нижнем регистре.
184+- IDE автоматически добавляет первое пространство при добавлении пользовательских параметров.
185+- При использовании в пакете вышеуказанное будет применяться только к параметрам, используемым для компиляции пакета, но не к проекту, использующему пакет.
186+
187+## Добавление некоторых параметров компоновщика для цели Mac OS X
188+
189+Компилятор использует для *Mac OS X* значение 'darwin' для *TargetOS*.
190+
191+``` pascal
192+if TargetOS = 'darwin' then begin
193+ LinkerOptions += ' -framework Cocoa';
194+ if TargetCPU = 'i386' then
195+ LinkerOptions += ' -framework OpenGL';
196+end;
197+```
198+
199+Примечание:
200+
201+- TargetOS и TargetCPU - это предопределенные в среде IDE макросы.
202+- Оператор **+=** добавляет строку или число.
203+- При добавлении нескольких опций вы должны добавить пробел между опциями.
204+- IDE автоматически добавляет первое пространство при добавлении параметров компоновщика.
205+- Вы можете вложить **begin**..**end** точно так же, как в Паскаль.
206+- Если выполняются оба условия, **LinkerOptions** будет содержать значение ' -framework Cocoa -framework OpenGL'.
207+- Среда IDE автоматически добавляет параметр -k при передаче параметров компоновщика компилятору.
208+- Вышеуказанное работает только для условных выражений проекта.
209+
210+## Добавление некоторых параметров компоновщика для Mac OS X для всех проектов с использованием пакета
211+
212+Пакеты имеют два разных набора опций. Набор, используемый для компиляции самого пакета, и параметры, добавленные ко всем проектам/пакетам, использующим пакет. Вам необходимо изменить параметр **usage** пакета:
213+
214+``` pascal
215+if TargetOS = 'darwin' then begin
216+ UsageLinkerOptions += ' -framework Cocoa';
217+ if TargetCPU = 'i386' then
218+ UsageLinkerOptions += ' -framework OpenGL';
219+end;
220+```
221+
222+## Добавление опции в пакет
223+
224+Если ваш пакет предоставляет некоторые дополнительные части, например возможность использовать opengl, вы можете определить макрос сборки. Далее объясняется, как это настроить шаг за шагом:
225+
226+Допустим, ваш пакет называется *Pkg1* и позволяет включить поддержку opengl, скомпилировав его с флагом **-dEnableOpenGL**. В пакете должен быть логический параметр **Pkg1_UseOpenGL** со значениями 'True' и 'False'.
227+
228+Откройте редактор пакетов 'pkg1', нажмите *compiler options* (Параметры компилятора), выберите страницу *IDE Macros* (Макросы IDE).
229+
230+Нажмите кнопку слева **+**, чтобы добавить новый макрос. Он будет называться 'Pkg1_Macro1'. Щелкните узел дерева, чтобы переименовать его в 'Pkg1_UseOpenGL'.
231+
232+Нажмите среднюю кнопку **+**, чтобы добавить новое значение макроса. Он будет называться 'Value1'. Щелкните узел дерева, чтобы переименовать его в 'True'. Повторите это для значения 'False'.
233+
234+Добавьте следующий код в текстовое поле Conditionals (Compiler Options / Other / Conditionals):
235+
236+``` pascal
237+if Pkg1_UseOpenGL = 'True' then
238+ CustomOptions := '-dEnableOpenGL';
239+```
240+
241+<figure>
242+<img src="Compileroptions_buildmacro_example1.png" title="Compileroptions_buildmacro_example1.png" />
243+<figcaption>Compileroptions_buildmacro_example1.png</figcaption>
244+</figure>
245+
246+Примечание:
247+
248+- Значение 'True' чувствительно к регистру. Поскольку значение обычно выбирается из поля со списком, вероятность опечаток отсутствует.
249+- Если пользователь не установил никакого значения для макроса, переменная 'Pkg1_UseOpenGL' не определена, а результат выражения - 'false'.
250+
251+## Добавление режима release/debug
252+
253+### Режим release/debug для вашего проекта и всех ваших пакетов
254+
255+Примечание: для этого требуется Lazarus 0.9.31 или выше.
256+
257+В параметрах компилятора проекта (Project / Project Options / Compiler Options / Build modes) добавьте режим сборки *Release*. Добавление этого режима сборки автоматически активирует его, поэтому все изменения параметров компилятора теперь выполняются только в этом режиме сборки.
258+
259+В "Set Macro Values" (Установить значения макроса) щелкните левый столбец в последней строке "(none)". Установите его в "MyPackageOptions". Примечание: его нет в поле со списком.
260+
261+Установите его значение в опции. Например, "-O3".
262+
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>
267+
268+Этот макрос можно использовать в параметрах компилятора проекта и во всех пакетах.
269+
270+Для каждого пакета выполните: Откройте параметры компилятора пакета, перейдите на страницу *Other*. Добавьте в *Custom options* текст \$(MyPackageOptions).
271+
272+### Специальный режим release/debug для одного пакета
273+
274+Допустим, нормальный режим - это режим debug, и вам нужен другой режим для release.
275+
276+Откройте редактор пакетов 'pkg1', нажмите *compiler options*, выберите страницу *Build Macros*.
277+
278+В разделе *Build macros* нажмите кнопку слева **+**, чтобы добавить новый макрос. Он будет называться 'Pkg1_Macro1'. Щелкните узел дерева, чтобы переименовать его в 'Pkg1_Release'.
279+
280+Нажмите среднюю кнопку **+**, чтобы добавить новое *значение* макроса. Он будет называться 'Value1'. Щелкните узел дерева, чтобы переименовать его в 'True'. Повторите это для значения 'False'.
281+
282+Добавьте следующий код в текстовое поле Conditionals:
283+
284+``` pascal
285+if Pkg1_Release = 'True' then
286+ // режим release
287+ CustomOptions := '-O3'
288+else
289+ // режим debug
290+ CustomOptions := '-Sa Ctroi';
291+```
292+
293+Примечание:
294+
295+- Значение 'True' чувствительно к регистру. Поскольку значение обычно выбирается из поля со списком, вероятность опечаток отсутствует.
296+- Если пользователь не установил никакого значения для макроса, переменная 'Pkg1_Release' не определена, а результат выражения - false.
297+
298+## Добавление макроса для путей поиска для работы с разными платформами
299+
300+Допустим, ваш пакет называется *Pkg1* и использует Windows GDI в MS Windows и X11 в Linux и BSD. Независимые от платформы модули находятся в основном каталоге пакета, и вы создали два подкаталога 'gdi' и 'x11', содержащие зависящие от платформы модули:
301+
302+``` bash
303+/path/of/your/package/pkg1/
304+ pkg1.lpk
305+ pkg1.pas
306+ generalunit.pas
307+ gdi/
308+ backend.pas
309+ x11/
310+ backend.pas
311+```
312+
313+Модуль *backend* в *gdi* следует использовать в Win32, Win64 и WinCE, а в Linux и FreeBSD следует использовать модуль *backend* в *x11*. Это означает, что путь поиска *Other unit files (-Fu)* (Другие файлы модулей (-Fu)) должен быть адаптирован в зависимости от целевой ОС. Ниже описывается, как настроить это шаг за шагом:
314+
315+Откройте редактор пакетов 'pkg1', щелкните параметры компилятора, выберите страницу *Build Macros* (Сборка макросов).
316+
317+Нажмите кнопку слева **+**, чтобы добавить новый макрос. Он будет называться 'Pkg1_Macro1'. Щелкните узел дерева, чтобы переименовать его в 'Pkg1_Backend'.
318+
319+Нажмите среднюю кнопку **+**, чтобы добавить новое значение макроса. Он будет называться 'Value1'. Щелкните узел дерева, чтобы переименовать его в 'gdi'. Повторите это для значения 'x11'.
320+
321+Добавьте следующий код в текстовое поле Conditionals:
322+
323+``` pascal
324+// выбираем значение для Pkg1_Backend в зависимости от TargetOS
325+if undefined(Pkg1_Backend) then begin
326+ if SrcOS='win' then
327+ Pkg1_Backend:='gdi'
328+ else
329+ Pkg1_Backend:='x11';
330+end;
331+```
332+
333+Макрос **\$(Pkg1_Backend)** станет доступным после нажатия кнопки ОК. Итак, нажмите 'Ok', чтобы закрыть параметры компилятора, и откройте его снова, чтобы использовать его в пути поиска *Other unit files (-Fu)* (Другие файлы модулей (-Fu)).
334+
335+<figure>
336+<img src="Compileroptions_buildmacro_example2.png" title="Compileroptions_buildmacro_example2.png" />
337+<figcaption>Compileroptions_buildmacro_example2.png</figcaption>
338+</figure>
339+
340+Примечание:
341+
342+- Пользователь может изменить значение Pkg1_Backend. Поэтому рекомендуется заключить настройку в *if undefined(Pkg1_Backend)*.
343+- Вместо макроса SrcOS вы можете использовать `if (TargetOS='win32') or (TargetOS='win64') or (TargetOS='wince') then ...`
344+
345+---
346+*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