[Что следует превратить в опции Kconfig]
Когда принимаете решение, что походит ли что-нибудь для опций Kconfig, полезно отличать символы, у которых есть приглашение для модификации (prompt, или текстовая подсказка), и символы, у которых этого нет.
Если у символа есть prompt (например bool "Enable foo"), то пользователь может поменять значение символа в интерфейсе menuconfig или guiconfig (см. выше врезку "Интерактивные интерфейсы Kconfig"), либо вручную, редактированием файлов конфигурации. Соответственно символ без prompt-а пользователь не может поменять напрямую, ни в интерактивном интерфейсе, ни даже редактированием файлов конфигурации.
Помещайте prompt на символ только когда пользователю может быть целесообразно поменять его значение.
Символы без prompt-ов называются скрытыми, или невидимыми символами, потому что они не видны в menuconfig и guiconfig. Символы, у которых есть prompt, также могут быть невидимыми, если зависимости для них не удовлетворены.
Символы без prompt-ов нельзя конфигурировать пользователем напрямую (они получают свое значение из других символов), так что для них применяется меньше ограничений. Если некоторые унаследованные настройки проще вычислить в Kconfig, чем например во время сборки, то делайте это в Kconfig, однако разделяйте между собой символы с prompt-ами и без них.
См. далее секцию "Опциональные prompt" для получения информации о том, как работать с настройками, которые фиксированы на одних машинах и конфигурируются на других.
[Что не следует превращать в опции Kconfig]
В Zephyr конфигурация Kconfig выполняется после выбора целевой платы (target board). В целом не имеет смысла использовать Kconfig для значения, которое соответствует фиксированной, специфической для определенной машины настройке. Обычно вместо этого такие параметры настройки должны быть обработаны через devicetree.
В частности, избегайте добавлять новые опции Kconfig следующих типов:
Опции, которые задают устройство в системе по имени. Например, если вы пишете драйвер устройства I2C, то избегайте создания опции с именем MY_DEVICE_I2C_BUS_NAME, чтобы указать узел шины, котором управляет устройство. Для альтернативы см. "Device drivers that depend on other devices" документации [5].
Подобным образом, если ваше приложение зависит от аппаратной специфики устройства PWM для управления RGB LED, то избегайте создания опции наподобие MY_PWM_DEVICE_NAME. Для альтернативы см. "Applications that depend on board-specific devices" документации [5].
Опции, которые задают фиксированные аппаратные конфигурации. Например, избегайте опций Kconfig, указывающих ножку GPIO.
Альтернатива, применимая к драйверам устройства - определить спецификатор GPIO с типом массива phandle во время привязки (device binding), и используйте GPIO devicetree API из кода на языке C (см. "Hardware specific APIs" документации [6]). Подобный совет применим для других случаев, где devicetree.h предоставляет Hardware specific API для ссылки на другие узлы в системе. Для примеров поищите исходный код для драйверов, использующий эти вызовы API.
Могут подойти специфичные для приложения devicetree binding для идентификации свойств, особенных для определенной платы. Для примера см. tests/drivers/gpio/gpio_basic_api.
Для приложений в качестве альтернативы, основанной на devicetree, см. пример Blinky.
[Операторы select]
Оператор select используется для разрешения одного символа, т. е. установки его в y всякий раз, когда другой символ установлен в y. Например, следующий код заставляет CONSOLE принять y всякий раз, когда USB_CONSOLE установлено в y:
config CONSOLE
bool "Console support"
...
config USB_CONSOLE
bool "USB console support"
select CONSOLE
Далее будут рассмотрены типичные случаи правильного и ошибочного использования select.
Неправильный select. Оператор select может поначалу казаться полезной функцией, но при чрезмерном использовании может вызывать проблемы.
Например, к символу CONSOLE добавляется новая зависимость разработчиком, который не знает о символе USB_CONSOLE (или просто забыл о нем):
config CONSOLE
bool "Console support"
depends on STRING_ROUTINES
Теперь разрешение USB_CONSOLE принуждает установку CONSOLE в y, даже если STRING_ROUTINES установлено в n. Для исправления этой проблемы должна быть также добавлена зависимость STRING_ROUTINES к USB_CONSOLE:
config USB_CONSOLE
bool "USB console support"
select CONSOLE
depends on STRING_ROUTINES
...
config STRING_ROUTINES
bool "Include string routines"
Часто встречаются более коварные случае с зависимостями, унаследованными из операторов if и menu.
Альтернативной попыткой исправить проблему может быть превращение зависимостей в другой select:
config CONSOLE
bool "Console support"
select STRING_ROUTINES
...
config USB_CONSOLE
bool "USB console support"
select CONSOLE
На практике это часто наоборот усиливает проблему, потому что любые зависимости добавленные к STRING_ROUTINES, нужно теперь копировать как в CONSOLE, так и в USB_CONSOLE.
Как правило, всякий раз при обновлении зависимости символа обновляются зависимости всех символов, которые (явно или косвенно) выбирают его. На практике это часто упускается из виду, даже для самого простого случая, показанного выше.
В частности, следует избегать цепочек символов, где каждый символ выбирает другой, кроме простых вспомогательных символов, как это рассматривается далее в секции "Использование select для helper-символов".
Либеральное использование select также приводит к тому, что файлы Kconfig становятся трудно читаемыми, как из-за дополнительных зависимостей, так и из-за нелокального характера select, который скрывает способы, которыми символ может быть разрешен.
Альтернативы для select. Для примера из предыдущей секции лучшим решением будет превратить select в depends on:
config CONSOLE
bool "Console support"
...
config USB_CONSOLE
bool "USB console support"
depends on CONSOLE
Это делает невозможным генерацию недопустимой конфигурации, и означает, что зависимости должны обновляться только в одном месте.
Возражение для использования здесь depends on состоит в том, что файлы конфигурации, которые разрешают USB_CONSOLE, теперь также должны разрешить CONSOLE:
CONFIG_CONSOLE=y
CONFIG_USB_CONSOLE=y
Это сводится к компромиссу, однако если разрешение CONSOLE это норма, то адаптация должна сделать умолчание CONSOLE в y:
config CONSOLE
bool "Console support"
default y
Это дает в файлах конфигурации только одно присвоение:
Обратите внимание, что файлы конфигурации, которые не должны разрешать CONSOLE, теперь должны явно её запрещать:
Использование select для helper-символов. Хорошее и безопасное использование select для создание "helper" символов, которые захватывают некоторое условие. Такие helper-символы предпочтительно не должны содержать prompt или зависимостей.
Например, helper-символ для индикации, что определенный CPU/SoC содержит FPU, должен быть определен следующим образом:
config CPU_HAS_FPU
bool
help
If y, the CPU has an FPU
...
config SOC_FOO
bool "FOO SoC"
select CPU_HAS_FPU
...
config SOC_BAR
bool "BAR SoC"
select CPU_HAS_FPU
Это делает возможным для других символов проверку поддержки FPU традиционным способом, без просмотра определенных архитектур:
config FPU
bool "Support floating point operations"
depends on CPU_HAS_FPU
Альтернатива привела бы к зависимостям, наподобие следующих, которые возможно будут дублироваться в нескольких местах:
config FPU
bool "Support floating point operations"
depends on SOC_FOO || SOC_BAR || ...
Невидимые helper-символы могут быть также полезны без select. Например, следующий код определяет helper-символ, у которого значение y, если у машины есть произвольно определенный "большой” объем памяти:
config LARGE_MEM
def_bool MEM_SIZE >= 64
Этот пример - сокращение от следующего:
config LARGE_MEM
bool
default MEM_SIZE >= 64
[Рекомендации по select]
Если резюмировать все перечисленное, то можно выделить следующие практики для select:
● Избегайте выбора символов с prompt-ми или зависимостями. Предпочтительно используйте depends on. Если depends on приводит к разрастанию в файлах конфигурации, рассмотрите возможность добавления Kconfig default для наиболее общего значения.
Редкие исключения могут относиться к случаям, когда вы уверены, что зависимости выбираемого или выбранного символа не будут рассинхронизированы, например при работе с двумя простыми символами, определенными близко друг к другу, с одинаковыми if.
Здравый смысл здесь применим, однако имейте в виду, что select часто на практике приводит к проблемам. Оператор depends on обычно более чистое и безопасное решение.
● Делайте сколько угодно select для простых helper-символов без prompt-ов и зависимостей. Это хороший инструмент для упрощения файлов Kconfig.
[Условные подключения]
Блоки if добавляют зависимости к каждому элементу в пределах if, как если бы использовался оператор depends on.
Общее недопонимание, связанное с if - предполагать, что следующий код условно подключает файл конфигурации Kconfig.other:
if DEP
source "Kconfig.other"
endif
В реальности условных включений в Kconfig нет. У if нет специального назначения, касающегося source.
Примечание: условное подключение будет невозможно реализовать, потому что условия if могут содержать (явно или косвенно) ссылки вперед на символы, которые еще не определены.
Скажем, Kconfig.other, упомянутый выше, содержит такое определение:
config FOO
bool "Support foo"
В этом случае FOO закончится следующим определением:
config FOO
bool "Support foo"
depends on DEP
Следует отметить, что избыточно добавлять depends on DEP к определению FOO в Kconfig.other, потому что зависимость DEP уже добавлена if DEP.
В общем случае старайтесь избегать избыточных зависимостей. Они могут сделать структуру файлов Kconfig трудной для понимания, и также делают изменения более подверженными ошибкам, поскольку может быть трудно обнаружить, что одна и та же зависимость добавляется дважды.
[Застрявшие символы в menuconfig и guiconfig]
Есть некий тонкий глюк, связанный с взаимозависимыми символами, у которых есть prompt. Рассмотрим такие символы:
config FOO
bool "Foo"
config STACK_SIZE
hex "Stack size"
default 0x200 if FOO
default 0x100
Предположим, что есть намерение использовать более крупный стек при каждом разрешении FOO, и что изначально в конфигурации FOO запрещен. Также помните, что Zephyr создает начальную конфигурацию zephyr/.config в директории build путем слияния файлов конфигурации (например, подключения prj.conf). Этот файл конфигурации существует перед тем, как будет запущен menuconfig или guiconfig.
При первом входе в интерфейс конфигурации значение STACK_SIZE равно 0x100, как и ожидалось. После разрешения FOO, вы можете справедливо ожидать, что значение STACK_SIZE поменяется на 0x200, но оно останется 0x100.
Чтобы понять, что происходит, вспомните, что у STACK_SIZE есть prompt, а значит этот параметр конфигурируется пользователем, и имейте в виду, что все действия Kconfig происходят от начальной конфигурации:
Поскольку Kconfig не может знать, пришло ли значение 0x100 от умолчания, или было введено пользователем, он должен предположить, что значение пришло от пользователя. Поскольку STACK_SIZE конфигурируется пользователем, то соблюдается значение из конфигурации, и любые умолчания символа игнорируются. Вот почему STACK_SIZE "замораживается" на 0x100, когда переключается FOO.
Правильное исправление зависит от того, что необходимо получить. Могут быть разные сценарии, для которых подойдут разные советы:
● Если STACK_SIZE может всегда быть получен автоматически, и не надо, чтобы его конфигурировал пользователь, то просто удалите prompt:
config STACK_SIZE
hex
default 0x200 if FOO
default 0x100
Символы без prompt-ов игнорируют любое значение из сохраненной конфигурации.
● Если STACK_SIZE обычно должен конфигурироваться пользователем, но должен быть установлен в 0x200, когда разрешается FOO, то запретите его prompt, когда FOO разрешен, как описано в секции "Опциональные prompt":
config STACK_SIZE
hex "Stack size" if !FOO
default 0x200 if FOO
default 0x100
● Если STACK_SIZE обычно должен вычисляться автоматически, однако нуждается в установке пользовательского значения в редких ситуациях, то добавьте другую опцию, которая делает параметр STACK_SIZE конфигурируемым пользователем:
config CUSTOM_STACK_SIZE
bool "Use a custom stack size"
help
Enable this if you need to use a custom stack size. When disabled, a
suitable stack size is calculated automatically.
config STACK_SIZE
hex "Stack size" if CUSTOM_STACK_SIZE
default 0x200 if FOO
default 0x100
Пока CUSTOM_STACK_SIZE запрещен, STACK_SIZE будет игнорировать значение из сохраненной конфигурации.
Хорошая идея - попробовать изменять параметры в интерфейсе menuconfig или guiconfig, чтобы убедиться, что все идет как надо. Это особенно справедливо при введении таких довольно сложных конструкций.
[Назначение значений символам, у которых нет prompt]
Присваивания скрытых (так называемых невидимых, у которых нет prompt) символов в файлах конфигурации всегда игнорируются. Скрытые символы всегда получают свои значения косвенно, от других символов, например через default и select.
Общим источником путаницы является открытие выходного файла конфигурации (zephyr/.config), где видно множество присвоений скрытым символам, откуда делается ошибочное предположение, что эти назначения должны соблюдаться, когда конфигурация считывается Kconfig. В реальности все присваивания скрытым символам в zephyr/.config игнорируются системой Kconfig, как и для других файлов конфигурации.
Чтобы понять, почему zephyr/.config все еще включает присваивания скрытым символам, нужно вспомнить, что zephyr/.config обслуживает 2 отдельные функции:
1. Хранит сохраненную конфигурацию.
2. Хранит вывод конфигурации. Файл zephyr/.config парсится файлами CMake, чтобы они могли запрашивать настройки конфигурации.
Таким образом, присвоения скрытых символов в zephyr/.config это просто вывод конфигурации. Сам Kconfig игнорирует присваивания скрытым символам, когда вычисляет значения символов.
Примечание: минимальная конфигурация, которая может быть сгенерирована в интерфейсах menuconfig и guiconfig, можно рассматривать как наиболее близкой к только что сохраненной конфигурации, без полного вывода конфигурации.
[Оператор depends on и символы string/int/hex]
Оператор depends on работает не только для символов bool, но также и для символов string, int и hex (и для choice).
Kconfig-определения ниже будут скрывать символ FOO_DEVICE_FREQUENCY, и запретят любой вывод конфигурации для него, когда запрещен FOO_DEVICE.
config FOO_DEVICE
bool "Foo device"
config FOO_DEVICE_FREQUENCY
int "Foo device frequency"
depends on FOO_DEVICE
В общем хорошей идеей будет проверить, что в интерфейсе menuconfig/guiconfig отображаются только соответствующие символы. Если показывать FOO_DEVICE_FREQUENCY, когда FOO_DEVICE запрещен (и возможно скрыт), то это делает трудно понимаемой взаимосвязь между этими символами, даже если код никогда не смотрит на FOO_DEVICE_FREQUENCY, когда FOO_DEVICE запрещен.
[Символы menuconfig]
Если за определением символа FOO немедленно следуют другие символы, которые зависят от FOO, то эти символы становятся дочерними по отношению к FOO. Если FOO определен с config FOO, то дочерние элементы отображаются с отступом относительно FOO. Определение вместо этого FOO через menuconfig FOO поместит дочерние элементы в отдельное меню, корнем которого будет FOO.
Оператор menuconfig не влияет на вычисление значений, это только опция отображения. Применение menuconfig может сократить количество пунктов в меню, и упростить структуру меню для навигации по нему. Например, у вас есть следующие определения:
menu "Foo subsystem"
config FOO_SUBSYSTEM
bool "Foo subsystem"
if FOO_SUBSYSTEM
config FOO_FEATURE_1
bool "Foo feature 1"
config FOO_FEATURE_2
bool "Foo feature 2"
config FOO_FREQUENCY
int "Foo frequency"
... lots of other FOO-related symbols
endif # FOO_SUBSYSTEM
endmenu
В этом случае возможно лучшим решением будет свернуть FOO_SUBSYSTEM в символ menuconfig:
menuconfig FOO_SUBSYSTEM
bool "Foo subsystem"
if FOO_SUBSYSTEM
config FOO_FEATURE_1
bool "Foo feature 1"
config FOO_FEATURE_2
bool "Foo feature 2"
config FOO_FREQUENCY
int "Foo frequency"
... lots of other FOO-related symbols
endif # FOO_SUBSYSTEM
В интерфейсе menuconfig это будет выглядеть следующим образом:
Обратите внимание, что определять menuconfig без дочерних символов не имеет смысла. Этого следует избегать, потому что будет выглядеть идентично символу со всеми невидимыми дочерними символами:
[*] I have no children ----
[*] All my children are invisible ----
[Проверка изменений в menuconfig/guiconfig]
Когда в файлы Kconfig добавляются новые символы, или делаются другие изменения, хорошей идеей будет просмотреть впоследствии эти символы в интерфейсе menuconfig или guiconfig. Чтобы быстро перейти к нужному символу, пользуйтесь функцией клавиши /.
Вот что следует проверить:
● Символы размещены в походящем месте? Удостоверьтесь, что они находятся в меню там, где больше всего подходят по смыслу, радом со связанными символами.
Если один символ зависит от другого, то часто хорошей идеей будет поместить зависимый символ сразу после символа, от которого он зависит. Он будет затем в интерфейсе menuconfig показан с отступом от родительского символа, и в guiconfig в отдельном меню родительского символа. Это также работает, если несколько символов размещены после символа, от которого они зависят.
● Легко ли из текста prompt понять назначение символа?
● Если добавляется несколько символов, все ли комбинации значений, которые они устанавливают, имеют смысл?
Например, если добавлены 2 символа FOO_SUPPORT и NO_FOO_SUPPORT, и оба могут быть разрешены одновременно, то это дает бессмысленную конфигурацию. В таком случае может быть будет лучше оставить только символ FOO_SUPPORT.
● Есть ли дублированные зависимости?
Это можно проверить, если выбрать символ и нажать ?, чтобы просмотреть информацию символа. Если есть дублированные зависимости, то используйте путь Included via ... в информации символа, чтобы определить, откуда они берутся.
[Проверка изменений с помощью scripts/kconfig/lint.py]
После того, как вы сделали изменения Kconfig, можно использовать скрипт scripts/kconfig/lint.py для проверки наличия некоторых потенциальных проблем, наподобие не используемых символов и символов, которые нельзя разрешить. Используйте --help для просмотра доступных опций.
Некоторые проверки довольно эвристические, так что помеченный после проверки символ не обязательно содержит проблему. Если проверка возвращает ложное положительное значение, например из-за вставки токена в C (CONFIG_FOO_##index##_BAR), то просто игнорируйте её.
Когда исследуется неизвестный символ FOO_BAR, хорошей идеей будет запустить git grep FOO_BAR, чтобы найти ссылки на него. Также рекомендуется искать по некоторой части имени символа, например git grep FOO и git grep BAR, поскольку это может помочь раскрыть вставку токена.
[Рекомендации по стилю и сокращения]
В этой секции даны некоторые рекомендации по оформлению файлов Kconfig и сокращения.
Оформление общих зависимостей. Если последовательность символы/choice имеют общую зависимость, зависимость может быть обработана с помощью if. В качестве примера рассмотрим код:
config FOO
bool "Foo"
depends on DEP
config BAR
bool "Bar"
depends on DEP
choice
prompt "Choice"
depends on DEP
config BAZ
bool "Baz"
config QAZ
bool "Qaz"
endchoice
Здесь зависимость DEP может быть обработана следующим образом:
if DEP
config FOO
bool "Foo"
config BAR
bool "Bar"
choice
prompt "Choice"
config BAZ
bool "Baz"
config QAZ
bool "Qaz"
endchoice
endif # DEP
Примечание: внутренне вторая версия кода трансформируется в первую.
Если последовательность символы/choice с общими зависимостями все находятся в одном меню, то зависимость можно поместить в само меню:
menu "Foo features"
depends on FOO_SUPPORT
config FOO_FEATURE_1
bool "Foo feature 1"
config FOO_FEATURE_2
bool "Foo feature 2"
endmenu
Если FOO_SUPPORT установлено в n, то пропадет все меню.
Избыточные значения по умолчанию. Символы bool неявно по умолчанию получают значения n, и строковые символы неявно по умолчанию получают пустые строки. Таким образом, default n и default "" (почти) всегда избыточны.
Рекомендуемый стиль в Zephyr пропускать избыточные значения по умолчанию для символов bool и string. Это также дает более чистую документацию (Implicitly defaults to n instead of n if < dependencies, possibly inherited>).
Примечание: есть один случай, когда умолчание n/"" не избыточно, когда определение символа в нескольких местах, и есть необходимость в его переопределении, например default y в последующем определении.
Однако для символов int и hex умолчания всегда должны присутствовать, поскольку они неявно используются по умолчанию для пустой строки. Это нужно в частности для совместимости с инструментами C Kconfig, хотя неявное значение по умолчанию 0 может быть менее вероятным по сравнению с другими типами символов.
Общие сокращения Kconfig. В Kconfig есть 2 сокращения, касающихся prompt и default.
● < type> "prompt" сокращение для одновременного указания типа и текста prompt. Например, следующие два определения эквивалентны:
config FOO
bool "foo"
config FOO
bool
prompt "foo"
В Zephyr первый стиль является сокращением и более предпочтителен.
● def_< type> < value> сокращение для одновременного указания и типа, и значения. Например, следующие два определения эквивалентны:
config FOO
def_bool BAR && BAZ
config FOO
bool
default BAR && BAZ
Использование обоих сокращений < type> "prompt" и def_< type> < value> в одном и том же определении будет избыточным, потому что тип определяется дважды.
Сокращение def_< type> < value> обычно полезно только для символов без prompt, и обычно неясно.
Примечание: для символов, определенных в нескольких местах (например файле Kconfig.defconfig в Zephyr), лучше всегда давать тип символу только в "базовом" определении символа, и использовать default (вместо def_< type> value) для остальных определений. Таким образом, если базовое определение символа удалено, то символ останется без типа, что приведен к генерации предупреждения, указывающего на другие определения символа. Это упростит поиск и удаление дополнительных определений символа.
Строки prompt. Для символа Kconfig, который разрешает драйвер/подсистему FOO, рассмотрите возможность указания только "Foo" в качестве текста prompt вместо того, чтобы указывать "Enable Foo support" или что-то подобное. Это обычно будет яснее в контексте опции, которая может быть переключена on/off, что делает сущности более целостными.
Комментарии заголовка и другие обозначения. Чтобы помочь удерживать конфигурацию целостной, придерживайтесь следующих правил.
● Используйте следующий формат для любых комментариев заголовка в начале файлов Kconfig:
# < Обзор символов, определенных в этом файле, предпочтительно на English >
(пустая стока)
# Copyright (c) 2019 ...
# SPDX-License-Identifier: < лицензия>
(пустая стока)
(определения Kconfig)
● Форматируйте комментарии как # Comment вместо #Comment.
● Поместите пустую строку перед/после каждого if/endif верхнего уровня.
● Используйте один символ табуляции для каждого отступа.
● Делайте отступ текста help с двумя дополнительными пробелами.
[Менее известные и используемые возможности Kconfig]
В этой секции перечислены некоторые менее ясные принципы поведения и функции Kconfig, которые все еще могут быть полезными.
Оператор imply. Этот оператор подобен select, однако учитывает зависимости и не устанавливает значение принудительно. Например, следующих код может использоваться для включения поддержки USB-клавиатуры по умолчанию на FOO SoC, все еще сохраняя для пользователя возможность это выключить:
config SOC_FOO
bool "FOO SoC"
imply USB_KEYBOARD
...
config USB_KEYBOARD
bool "USB keyboard support"
Таким образом, imply действует как предложение, в то время как select принудительно устанавливает значение.
Опциональные prompt. В prompt символа может быть помещено условие, чтобы сделать это конфигурируемым для пользователя. Например, значение MASK, которое жестко закодировано в 0xFF на некоторых платах, и конфигурируется на других, может быть выражено следующим образом:
config MASK
hex "Bitmask" if HAS_CONFIGURABLE_MASK
default 0xFF
Примечание: это сокращение для следующего:
config MASK
hex
prompt "Bitmask" if HAS_CONFIGURABLE_MASK
default 0xFF
Helper-символ HAS_CONFIGURABLE_MASK будет выбран платами, чтобы указать, что MASK можно конфигурировать. Когда MASK конфигурируема, она также по умолчанию будет 0xFF.
Опциональные choice. Определение choice с ключевым словом optional позволяет выключить весь choice при выборе ни одного из символов:
choice
prompt "Use legacy protocol"
optional
config LEGACY_PROTOCOL_1
bool "Legacy protocol 1"
config LEGACY_PROTOCOL_2
bool "Legacy protocol 2"
endchoice
В интерфейсе menuconfig это будет отображено, например, как [*] Use legacy protocol (Legacy protocol 1) --->, где choice может быть переключен в off того, чтобы не был выбран ни один из символов.
Условия visible if. Помещение условия visible if в меню скроет меню и все символы в нем, позволяя по-прежнему оставлять значения умолчания символов.
В качестве мотивирующего примера рассмотрим код:
menu "Foo subsystem"
depends on HAS_CONFIGURABLE_FOO
config FOO_SETTING_1
int "Foo setting 1"
default 1
config FOO_SETTING_2
int "Foo setting 2"
default 2
endmenu
Когда HAS_CONFIGURABLE_FOO установлено в n, для FOO_SETTING_1 и FOO_SETTING_2 не генерируется вывод конфигурации, поскольку код выше логически становится эквивалентен коду:
config FOO_SETTING_1
int "Foo setting 1"
default 1
depends on HAS_CONFIGURABLE_FOO
config FOO_SETTING_2
int "Foo setting 2"
default 2
depends on HAS_CONFIGURABLE_FOO
Если мы хотим, чтобы символы все еще получили свои значения по умолчанию, даже когда HAS_CONFIGURABLE_FOO установлено в n, но они не были конфигурируемыми для пользователя, то вместо этого мы можем использовать visible if:
menu "Foo subsystem"
visible if HAS_CONFIGURABLE_FOO
config FOO_SETTING_1
int "Foo setting 1"
default 1
config FOO_SETTING_2
int "Foo setting 2"
default 2
endmenu
Логически это эквивалентно следующему:
config FOO_SETTING_1
int "Foo setting 1" if HAS_CONFIGURABLE_FOO
default 1
config FOO_SETTING_2
int "Foo setting 2" if HAS_CONFIGURABLE_FOO
default 2
Примечание: см. секцию "Опциональные prompt" для информации по условиям в prompt.
Когда HAS_CONFIGURABLE установлено в n, мы теперь получим следующий вывод конфигурации для символов, вместо отсутствия вывода:
...
CONFIG_FOO_SETTING_1=1
CONFIG_FOO_SETTING_2=2
...
Комментарии
RSS лента комментариев этой записи