├── .gitignore ├── LICENSE.txt ├── MANIFEST.in ├── README.rst ├── alldefconfig.py ├── allmodconfig.py ├── allnoconfig.py ├── allyesconfig.py ├── defconfig.py ├── examples ├── Kmenuconfig ├── allnoconfig_walk.py ├── defconfig_oldconfig.py ├── dumpvars.py ├── eval_expr.py ├── find_symbol.py ├── help_grep.py ├── kconfiglib.py ├── list_undefined.py ├── menuconfig_example.py ├── merge_config.py ├── print_config_tree.py ├── print_sym_info.py └── print_tree.py ├── genconfig.py ├── guiconfig.py ├── kconfiglib.py ├── listnewconfig.py ├── makefile.patch ├── menuconfig.py ├── oldconfig.py ├── olddefconfig.py ├── savedefconfig.py ├── setconfig.py ├── setup.cfg ├── setup.py ├── tests ├── Kappend ├── Kassignable ├── Kchoice ├── Kdefconfig_existent ├── Kdefconfig_existent_but_n ├── Kdefconfig_nonexistent ├── Kdefconfig_srctree ├── Kdepcopy ├── Kdeploop0 ├── Kdeploop1 ├── Kdeploop10 ├── Kdeploop2 ├── Kdeploop3 ├── Kdeploop4 ├── Kdeploop5 ├── Kdeploop6 ├── Kdeploop7 ├── Kdeploop8 ├── Kdeploop9 ├── Kdirdep ├── Kescape ├── Keval ├── Kexpr_items ├── Kheader ├── Khelp ├── Kifremoval ├── Kimply ├── Kinclude_path ├── Kinclude_path_sourced_1 ├── Kinclude_path_sourced_2 ├── Kitemlists ├── Klocation ├── Klocation_sourced ├── Kmainmenu ├── Kmenuconfig ├── Kmisc ├── Kmissingrsource ├── Kmissingsource ├── Korder ├── Kpreprocess ├── Krange ├── Krecursive1 ├── Krecursive2 ├── Kreferenced ├── Krelation ├── Krepr ├── Kstr ├── Kundef ├── Kuserfunctions ├── Kvisibility ├── config_indented ├── config_set_bool ├── config_set_string ├── defconfig_1 ├── defconfig_2 ├── empty ├── kconfigfunctions.py ├── reltest ├── sub │ ├── Kconfig_symlink_2 │ ├── Kconfig_symlink_3 │ ├── Klocation_grsourced1 │ ├── Klocation_grsourced2 │ ├── Klocation_gsourced1 │ ├── Klocation_gsourced2 │ ├── Klocation_rsourced │ ├── defconfig_in_sub │ └── sub │ │ └── Kconfig_symlink_1 └── symlink └── testsuite.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.py[co] 2 | build/ 3 | *.egg-info/ 4 | dist/ 5 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011-2019, Ulf Magnusson 2 | 3 | Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. 4 | 5 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 6 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | # Include the license file in source distributions 2 | include LICENSE.txt 3 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | .. contents:: Table of contents 2 | :backlinks: none 3 | 4 | News 5 | ---- 6 | 7 | Dependency loop with recent linux-next kernels 8 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 9 | 10 | To fix issues with dependency loops on recent linux-next kernels, apply `this 11 | patch `_. Hopefully, 12 | it will be in ``linux-next`` soon. 13 | 14 | ``windows-curses`` is no longer automatically installed on Windows 15 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 16 | 17 | Starting with Kconfiglib 13.0.0, the `windows-curses 18 | `__ package is no longer 19 | automatically installed on Windows, and needs to be installed manually for the 20 | terminal ``menuconfig`` to work. 21 | 22 | This fixes installation of Kconfiglib on MSYS2, which is not compatible with 23 | ``windows-curses``. See `this issue 24 | `__. 25 | 26 | The ``menuconfig`` now shows a hint re. installing ``windows-curses`` when the 27 | ``curses`` module can't be imported on Windows. 28 | 29 | Sorry if this change caused problems! 30 | 31 | Overview 32 | -------- 33 | 34 | Kconfiglib is a `Kconfig 35 | `__ 36 | implementation in Python 2/3. It started out as a helper library, but now has a 37 | enough functionality to also work well as a standalone Kconfig implementation 38 | (including `terminal and GUI menuconfig interfaces `_ 39 | and `Kconfig extensions`_). 40 | 41 | The entire library is contained in `kconfiglib.py 42 | `_. The 43 | bundled scripts are implemented on top of it. Implementing your own scripts 44 | should be relatively easy, if needed. 45 | 46 | Kconfiglib is used exclusively by e.g. the `Zephyr 47 | `__, `esp-idf 48 | `__, and `ACRN 49 | `__ projects. It is also used for many small helper 50 | scripts in various projects. 51 | 52 | Since Kconfiglib is based around a library, it can be used e.g. to generate a 53 | `Kconfig cross-reference 54 | `_, using 55 | the same robust Kconfig parser used for other Kconfig tools, instead of brittle 56 | ad-hoc parsing. The documentation generation script can be found `here 57 | `__. 58 | 59 | Kconfiglib implements the recently added `Kconfig preprocessor 60 | `__. 61 | For backwards compatibility, environment variables can be referenced both as 62 | ``$(FOO)`` (the new syntax) and as ``$FOO`` (the old syntax). The old syntax is 63 | deprecated, but will probably be supported for a long time, as it's needed to 64 | stay compatible with older Linux kernels. The major version will be increased 65 | if support is ever dropped. Using the old syntax with an undefined environment 66 | variable keeps the string as is. 67 | 68 | Note: See `this issue `__ if 69 | you run into a "macro expanded to blank string" error with kernel 4.18+. 70 | 71 | See `this page 72 | `__ for some 73 | Kconfig tips and best practices. 74 | 75 | Installation 76 | ------------ 77 | 78 | Installation with pip 79 | ~~~~~~~~~~~~~~~~~~~~~ 80 | 81 | Kconfiglib is available on `PyPI `_ and can be 82 | installed with e.g. 83 | 84 | .. code:: 85 | 86 | $ pip(3) install kconfiglib 87 | 88 | Microsoft Windows is supported. 89 | 90 | The ``pip`` installation will give you both the base library and the following 91 | executables. All but two (``genconfig`` and ``setconfig``) mirror functionality 92 | available in the C tools. 93 | 94 | - `menuconfig `_ 95 | 96 | - `guiconfig `_ 97 | 98 | - `oldconfig `_ 99 | 100 | - `olddefconfig `_ 101 | 102 | - `savedefconfig `_ 103 | 104 | - `defconfig `_ 105 | 106 | - `alldefconfig `_ 107 | 108 | - `allnoconfig `_ 109 | 110 | - `allmodconfig `_ 111 | 112 | - `allyesconfig `_ 113 | 114 | - `listnewconfig `_ 115 | 116 | - `genconfig `_ 117 | 118 | - `setconfig `_ 119 | 120 | ``genconfig`` is intended to be run at build time. It generates a C header from 121 | the configuration and (optionally) information that can be used to rebuild only 122 | files that reference Kconfig symbols that have changed value. 123 | 124 | Starting with Kconfiglib version 12.2.0, all utilities are compatible with both 125 | Python 2 and Python 3. Previously, ``menuconfig.py`` only ran under Python 3 126 | (i.e., it's now more backwards compatible than before). 127 | 128 | **Note:** If you install Kconfiglib with ``pip``'s ``--user`` flag, make sure 129 | that your ``PATH`` includes the directory where the executables end up. You can 130 | list the installed files with ``pip(3) show -f kconfiglib``. 131 | 132 | All releases have a corresponding tag in the git repository, e.g. ``v14.1.0`` 133 | (the latest version). 134 | 135 | `Semantic versioning `_ is used. There's been ten small 136 | changes to the behavior of the API, a Windows packaging change, and a hashbang 137 | change to use ``python3`` 138 | (`1 `_, 139 | `2 `_, 140 | `3 `_, 141 | `4 `_, 142 | `5 `_, 143 | `6 `_, 144 | `7 `_, 145 | `8 `_, 146 | `9 `_, 147 | `10 `_, 148 | `Windows packaging change `_, 149 | `Python 3 hashbang change `_), 150 | which is why the major version is at 14 rather than 2. I do major version bumps 151 | for all behavior changes, even tiny ones, and most of these were fixes for baby 152 | issues in the early days of the Kconfiglib 2 API. 153 | 154 | Manual installation 155 | ~~~~~~~~~~~~~~~~~~~ 156 | 157 | Just drop ``kconfiglib.py`` and the scripts you want somewhere. There are no 158 | third-party dependencies, but the terminal ``menuconfig`` won't work on Windows 159 | unless a package like `windows-curses 160 | `__ is installed. 161 | 162 | Installation for the Linux kernel 163 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 164 | 165 | See the module docstring at the top of `kconfiglib.py `_. 166 | 167 | Python version compatibility (2.7/3.2+) 168 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 169 | 170 | Kconfiglib and all utilities run under both Python 2.7 and Python 3.2 and 171 | later. The code mostly uses basic Python features and has no third-party 172 | dependencies, so keeping it backwards-compatible is pretty low effort. 173 | 174 | The 3.2 requirement comes from ``argparse``. ``format()`` with unnumbered 175 | ``{}`` is used as well. 176 | 177 | A recent Python 3 version is recommended if you have a choice, as it'll give 178 | you better Unicode handling. 179 | 180 | Getting started 181 | --------------- 182 | 183 | 1. `Install `_ the library and the utilities. 184 | 185 | 2. Write `Kconfig 186 | `__ 187 | files that describe the available configuration options. See `this page 188 | `__ for some 189 | general Kconfig advice. 190 | 191 | 3. Generate an initial configuration with e.g. ``menuconfig``/``guiconfig`` or 192 | ``alldefconfig``. The configuration is saved as ``.config`` by default. 193 | 194 | For more advanced projects, the ``defconfig`` utility can be used to 195 | generate the initial configuration from an existing configuration file. 196 | Usually, this existing configuration file would be a minimal configuration 197 | file, as generated by e.g. ``savedefconfig``. 198 | 199 | 4. Run ``genconfig`` to generate a header file. By default, it is saved as 200 | ``config.h``. 201 | 202 | Normally, ``genconfig`` would be run automatically as part of the build. 203 | 204 | Before writing a header file or other configuration output, Kconfiglib 205 | compares the old contents of the file against the new contents. If there's 206 | no change, the write is skipped. This avoids updating file metadata like the 207 | modification time, and might save work depending on your build setup. 208 | 209 | Adding new configuration output formats should be relatively straightforward. 210 | See the implementation of ``write_config()`` in `kconfiglib.py 211 | `_. 212 | The documentation for the ``Symbol.config_string`` property has some tips as 213 | well. 214 | 215 | 5. To update an old ``.config`` file after the Kconfig files have changed (e.g. 216 | to add new options), run ``oldconfig`` (prompts for values for new options) 217 | or ``olddefconfig`` (gives new options their default value). Entering the 218 | ``menuconfig`` or ``guiconfig`` interface and saving the configuration will 219 | also update it (the configuration interfaces always prompt for saving 220 | on exit if it would modify the contents of the ``.config`` file). 221 | 222 | Due to Kconfig semantics, simply loading an old ``.config`` file performs an 223 | implicit ``olddefconfig``, so building will normally not be affected by 224 | having an outdated configuration. 225 | 226 | Whenever ``.config`` is overwritten, the previous version of the file is saved 227 | to ``.config.old`` (or, more generally, to ``$KCONFIG_CONFIG.old``). 228 | 229 | Using ``.config`` files as Make input 230 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 231 | 232 | ``.config`` files use Make syntax and can be included directly in Makefiles to 233 | read configuration values from there. This is why ``n``-valued 234 | ``bool``/``tristate`` values are written out as ``# CONFIG_FOO is not set`` (a 235 | Make comment) in ``.config``, allowing them to be tested with ``ifdef`` in 236 | Make. 237 | 238 | If you make use of this, you might want to pass ``--config-out `` to 239 | ``genconfig`` and include the configuration file it generates instead of 240 | including ``.config`` directly. This has the advantage that the generated 241 | configuration file will always be a "full" configuration file, even if 242 | ``.config`` is outdated. Otherwise, it might be necessary to run 243 | ``old(def)config`` or ``menuconfig``/``guiconfig`` before rebuilding with an 244 | outdated ``.config``. 245 | 246 | If you use ``--sync-deps`` to generate incremental build information, you can 247 | include ``deps/auto.conf`` instead, which is also a full configuration file. 248 | 249 | Useful helper macros 250 | ~~~~~~~~~~~~~~~~~~~~ 251 | 252 | The `include/linux/kconfig.h 253 | `_ 254 | header in the Linux kernel defines some useful helper macros for testing 255 | Kconfig configuration values. 256 | 257 | ``IS_ENABLED()`` is generally useful, allowing configuration values to be 258 | tested in ``if`` statements with no runtime overhead. 259 | 260 | Incremental building 261 | ~~~~~~~~~~~~~~~~~~~~ 262 | 263 | See the docstring for ``Kconfig.sync_deps()`` in `kconfiglib.py 264 | `_ for hints 265 | on implementing incremental builds (rebuilding just source files that reference 266 | changed configuration values). 267 | 268 | Running the ``scripts/basic/fixdep.c`` tool from the kernel on the output of 269 | ``gcc -MD `` might give you an idea of how it all fits together. 270 | 271 | Library documentation 272 | --------------------- 273 | 274 | Kconfiglib comes with extensive documentation in the form of docstrings. To view it, run e.g. 275 | the following command: 276 | 277 | .. code:: sh 278 | 279 | $ pydoc(3) kconfiglib 280 | 281 | For HTML output, add ``-w``: 282 | 283 | .. code:: sh 284 | 285 | $ pydoc(3) -w kconfiglib 286 | 287 | This will also work after installing Kconfiglib with ``pip(3)``. 288 | 289 | Documentation for other modules can be viewed in the same way (though a plain 290 | ``--help`` will work when they're run as executables): 291 | 292 | .. code:: sh 293 | 294 | $ pydoc(3) menuconfig/guiconfig/... 295 | 296 | A good starting point for learning the library is to read the module docstring 297 | (which you could also just read directly at the beginning of `kconfiglib.py 298 | `_). It 299 | gives an introduction to symbol values, the menu tree, and expressions. 300 | 301 | After reading the module docstring, a good next step is to read the ``Kconfig`` 302 | class documentation, and then the documentation for the ``Symbol``, ``Choice``, 303 | and ``MenuNode`` classes. 304 | 305 | Please tell me if something is unclear or can be explained better. 306 | 307 | Library features 308 | ---------------- 309 | 310 | Kconfiglib can do the following, among other things: 311 | 312 | - **Programmatically get and set symbol values** 313 | 314 | See `allnoconfig.py 315 | `_ and 316 | `allyesconfig.py 317 | `_, 318 | which are automatically verified to produce identical output to the standard 319 | ``make allnoconfig`` and ``make allyesconfig``. 320 | 321 | - **Read and write .config and defconfig files** 322 | 323 | The generated ``.config`` and ``defconfig`` (minimal configuration) files are 324 | character-for-character identical to what the C implementation would generate 325 | (except for the header comment). The test suite relies on this, as it 326 | compares the generated files. 327 | 328 | - **Write C headers** 329 | 330 | The generated headers use the same format as ``include/generated/autoconf.h`` 331 | from the Linux kernel. Output for symbols appears in the order that they're 332 | defined, unlike in the C tools (where the order depends on the hash table 333 | implementation). 334 | 335 | - **Implement incremental builds** 336 | 337 | This uses the same scheme as the ``include/config`` directory in the kernel: 338 | Symbols are translated into files that are touched when the symbol's value 339 | changes between builds, which can be used to avoid having to do a full 340 | rebuild whenever the configuration is changed. 341 | 342 | See the ``sync_deps()`` function for more information. 343 | 344 | - **Inspect symbols** 345 | 346 | Printing a symbol or other item (which calls ``__str__()``) returns its 347 | definition in Kconfig format. This also works for symbols defined in multiple 348 | locations. 349 | 350 | A helpful ``__repr__()`` is on all objects too. 351 | 352 | All ``__str__()`` and ``__repr__()`` methods are deliberately implemented 353 | with just public APIs, so all symbol information can be fetched separately as 354 | well. 355 | 356 | - **Inspect expressions** 357 | 358 | Expressions use a simple tuple-based format that can be processed manually 359 | if needed. Expression printing and evaluation functions are provided, 360 | implemented with public APIs. 361 | 362 | - **Inspect the menu tree** 363 | 364 | The underlying menu tree is exposed, including submenus created implicitly 365 | from symbols depending on preceding symbols. This can be used e.g. to 366 | implement menuconfig-like functionality. 367 | 368 | See `menuconfig.py 369 | `_/`guiconfig.py 370 | `_ and the 371 | minimalistic `menuconfig_example.py 372 | `_ 373 | example. 374 | 375 | Kconfig extensions 376 | ~~~~~~~~~~~~~~~~~~ 377 | 378 | The following Kconfig extensions are available: 379 | 380 | - ``source`` supports glob patterns and includes each matching file. A pattern 381 | is required to match at least one file. 382 | 383 | A separate ``osource`` statement is available for cases where it's okay for 384 | the pattern to match no files (in which case ``osource`` turns into a no-op). 385 | 386 | - A relative ``source`` statement (``rsource``) is available, where file paths 387 | are specified relative to the directory of the current Kconfig file. An 388 | ``orsource`` statement is available as well, analogous to ``osource``. 389 | 390 | - Preprocessor user functions can be defined in Python, which makes it simple 391 | to integrate information from existing Python tools into Kconfig (e.g. to 392 | have Kconfig symbols depend on hardware information stored in some other 393 | format). 394 | 395 | See the *Kconfig extensions* section in the 396 | `kconfiglib.py `_ 397 | module docstring for more information. 398 | 399 | - ``def_int``, ``def_hex``, and ``def_string`` are available in addition to 400 | ``def_bool`` and ``def_tristate``, allowing ``int``, ``hex``, and ``string`` 401 | symbols to be given a type and a default at the same time. 402 | 403 | These can be useful in projects that make use of symbols defined in multiple 404 | locations, and remove some Kconfig inconsistency. 405 | 406 | - Environment variables are expanded directly in e.g. ``source`` and 407 | ``mainmenu`` statements, meaning ``option env`` symbols are redundant. 408 | 409 | This is the standard behavior with the new `Kconfig preprocessor 410 | `__, 411 | which Kconfiglib implements. 412 | 413 | ``option env`` symbols are accepted but ignored, which leads the caveat that 414 | they must have the same name as the environment variables they reference 415 | (Kconfiglib warns if the names differ). This keeps Kconfiglib compatible with 416 | older Linux kernels, where the name of the ``option env`` symbol always 417 | matched the environment variable. Compatibility with older Linux kernels is 418 | the main reason ``option env`` is still supported. 419 | 420 | The C tools have dropped support for ``option env``. 421 | 422 | - Two extra optional warnings can be enabled by setting environment variables, 423 | covering cases that are easily missed when making changes to Kconfig files: 424 | 425 | * ``KCONFIG_WARN_UNDEF``: If set to ``y``, warnings will be generated for all 426 | references to undefined symbols within Kconfig files. The only gotcha is 427 | that all hex literals must be prefixed with ``0x`` or ``0X``, to make it 428 | possible to distinguish them from symbol references. 429 | 430 | Some projects (e.g. the Linux kernel) use multiple Kconfig trees with many 431 | shared Kconfig files, leading to some safe undefined symbol references. 432 | ``KCONFIG_WARN_UNDEF`` is useful in projects that only have a single 433 | Kconfig tree though. 434 | 435 | ``KCONFIG_STRICT`` is an older alias for this environment variable, 436 | supported for backwards compatibility. 437 | 438 | * ``KCONFIG_WARN_UNDEF_ASSIGN``: If set to ``y``, warnings will be generated 439 | for all assignments to undefined symbols within ``.config`` files. By 440 | default, no such warnings are generated. 441 | 442 | This warning can also be enabled/disabled by setting 443 | ``Kconfig.warn_assign_undef`` to ``True``/``False``. 444 | 445 | Other features 446 | -------------- 447 | 448 | - **Single-file implementation** 449 | 450 | The entire library is contained in `kconfiglib.py 451 | `_. 452 | 453 | The tools implemented on top of it are one file each. 454 | 455 | - **Robust and highly compatible with the C Kconfig tools** 456 | 457 |  The `test suite `_ 458 | automatically compares output from Kconfiglib and the C tools 459 | by diffing the generated ``.config`` files for the real kernel Kconfig and 460 | defconfig files, for all ARCHes. 461 | 462 | This currently involves comparing the output for 36 ARCHes and 498 defconfig 463 | files (or over 18000 ARCH/defconfig combinations in "obsessive" test suite 464 | mode). All tests are expected to pass. 465 | 466 | A comprehensive suite of selftests is included as well. 467 | 468 | - **Not horribly slow despite being a pure Python implementation** 469 | 470 | The `allyesconfig.py 471 | `_ 472 | script currently runs in about 1.3 seconds on the Linux kernel on a Core i7 473 | 2600K (with a warm file cache), including the ``make`` overhead from ``make 474 | scriptconfig``. Note that the Linux kernel Kconfigs are absolutely massive 475 | (over 14k symbols for x86) compared to most projects, and also have overhead 476 | from running shell commands via the Kconfig preprocessor. 477 | 478 | Kconfiglib is especially speedy in cases where multiple ``.config`` files 479 | need to be processed, because the ``Kconfig`` files will only need to be parsed 480 | once. 481 | 482 | For long-running jobs, `PyPy `_ gives a big performance 483 | boost. CPython is faster for short-running jobs as PyPy needs some time to 484 | warm up. 485 | 486 | Kconfiglib also works well with the 487 | `multiprocessing `_ 488 | module. No global state is kept. 489 | 490 | - **Generates more warnings than the C implementation** 491 | 492 | Generates the same warnings as the C implementation, plus additional ones. 493 | Also detects dependency and ``source`` loops. 494 | 495 | All warnings point out the location(s) in the ``Kconfig`` files where a 496 | symbol is defined, where applicable. 497 | 498 | - **Unicode support** 499 | 500 | Unicode characters in string literals in ``Kconfig`` and ``.config`` files are 501 | correctly handled. This support mostly comes for free from Python. 502 | 503 | - **Windows support** 504 | 505 | Nothing Linux-specific is used. Universal newlines mode is used for both 506 | Python 2 and Python 3. 507 | 508 | The `Zephyr `_ project uses Kconfiglib to 509 | generate ``.config`` files and C headers on Linux as well as Windows. 510 | 511 | - **Internals that (mostly) mirror the C implementation** 512 | 513 | While being simpler to understand and tweak. 514 | 515 | Menuconfig interfaces 516 | --------------------- 517 | 518 | Three configuration interfaces are currently available: 519 | 520 | - `menuconfig.py `_ 521 | is a terminal-based configuration interface implemented using the standard 522 | Python ``curses`` module. ``xconfig`` features like showing invisible symbols and 523 | showing symbol names are included, and it's possible to jump directly to a symbol 524 | in the menu tree (even if it's currently invisible). 525 | 526 | .. image:: https://raw.githubusercontent.com/ulfalizer/Kconfiglib/screenshots/screenshots/menuconfig.gif 527 | 528 | *There is now also a show-help mode that shows the help text of the currently 529 | selected symbol in the help window at the bottom.* 530 | 531 | Starting with Kconfiglib 12.2.0, ``menuconfig.py`` runs under both Python 2 532 | and Python 3 (previously, it only ran under Python 3, so this was a 533 | backport). Running it under Python 3 provides better support for Unicode text 534 | entry (``get_wch()`` is not available in the ``curses`` module on Python 2). 535 | 536 | There are no third-party dependencies on \*nix. On Windows, 537 | the ``curses`` modules is not available by default, but support 538 | can be added by installing the ``windows-curses`` package: 539 | 540 | .. code-block:: shell 541 | 542 | $ pip install windows-curses 543 | 544 | This uses wheels built from `this repository 545 | `_, which is in turn 546 | based on Christoph Gohlke's `Python Extension Packages for Windows 547 | `_. 548 | 549 | See the docstring at the top of `menuconfig.py 550 | `_ for 551 | more information about the terminal menuconfig implementation. 552 | 553 | - `guiconfig.py 554 | `_ is a 555 | graphical configuration interface written in `Tkinter 556 | `_. Like ``menuconfig.py``, 557 | it supports showing all symbols (with invisible symbols in red) and jumping 558 | directly to symbols. Symbol values can also be changed directly from the 559 | jump-to dialog. 560 | 561 | When single-menu mode is enabled, a single menu is shown at a time, like in 562 | the terminal menuconfig. Only this mode distinguishes between symbols defined 563 | with ``config`` and symbols defined with ``menuconfig``. 564 | 565 | ``guiconfig.py`` has been tested on X11, Windows, and macOS, and is 566 | compatible with both Python 2 and Python 3. 567 | 568 | Despite being part of the Python standard library, ``tkinter`` often isn't 569 | included by default in Python installations on Linux. These commands will 570 | install it on a few different distributions: 571 | 572 | - Ubuntu: ``sudo apt install python-tk``/``sudo apt install python3-tk`` 573 | 574 | - Fedora: ``dnf install python2-tkinter``/``dnf install python3-tkinter`` 575 | 576 | - Arch: ``sudo pacman -S tk`` 577 | 578 | - Clear Linux: ``sudo swupd bundle-add python3-tcl`` 579 | 580 | Screenshot below, with show-all mode enabled and the jump-to dialog open: 581 | 582 | .. image:: https://raw.githubusercontent.com/ulfalizer/Kconfiglib/screenshots/screenshots/guiconfig.png 583 | 584 | To avoid having to carry around a bunch of GIFs, the image data is embedded 585 | in ``guiconfig.py``. To use separate GIF files instead, change 586 | ``_USE_EMBEDDED_IMAGES`` to ``False`` in ``guiconfig.py``. The image files 587 | can be found in the `screenshots 588 | `_ 589 | branch. 590 | 591 | I did my best with the images, but some are definitely only art adjacent. 592 | Touch-ups are welcome. :) 593 | 594 | - `pymenuconfig `_, built by `RomaVis 595 | `_, is an older portable Python 2/3 TkInter 596 | menuconfig implementation. 597 | 598 | Screenshot below: 599 | 600 | .. image:: https://raw.githubusercontent.com/RomaVis/pymenuconfig/master/screenshot.PNG 601 | 602 | While working on the terminal menuconfig implementation, I added a few APIs 603 | to Kconfiglib that turned out to be handy. ``pymenuconfig`` predates 604 | ``menuconfig.py`` and ``guiconfig.py``, and so didn't have them available. 605 | Blame me for any workarounds. 606 | 607 | Examples 608 | -------- 609 | 610 | Example scripts 611 | ~~~~~~~~~~~~~~~ 612 | 613 | The `examples/ `_ directory contains some simple example scripts. Among these are the following ones. Make sure you run them with the latest version of Kconfiglib, as they might make use of newly added features. 614 | 615 | - `eval_expr.py `_ evaluates an expression in the context of a configuration. 616 | 617 | - `find_symbol.py `_ searches through expressions to find references to a symbol, also printing a "backtrace" with parents for each reference found. 618 | 619 | - `help_grep.py `_ searches for a string in all help texts. 620 | 621 | - `print_tree.py `_ prints a tree of all configuration items. 622 | 623 | - `print_config_tree.py `_ is similar to ``print_tree.py``, but dumps the tree as it would appear in ``menuconfig``, including values. This can be handy for visually diffing between ``.config`` files and different versions of ``Kconfig`` files. 624 | 625 | - `list_undefined.py `_ finds references to symbols that are not defined by any architecture in the Linux kernel. 626 | 627 | - `merge_config.py `_ merges configuration fragments to produce a complete .config, similarly to ``scripts/kconfig/merge_config.sh`` from the kernel. 628 | 629 | - `menuconfig_example.py `_ implements a configuration interface that uses notation similar to ``make menuconfig``. It's deliberately kept as simple as possible to demonstrate just the core concepts. 630 | 631 | Real-world examples 632 | ~~~~~~~~~~~~~~~~~~~ 633 | 634 | - `kconfig.py 635 | `_ 636 | from the `Zephyr `_ project handles 637 | ``.config`` and header file generation, also doing configuration fragment 638 | merging 639 | 640 | - `genrest.py 641 | `_ 642 | generates a Kconfig symbol cross-reference, which can be viewed `here 643 | `__ 644 | 645 | - `CMake and IDE integration 646 | `_ from 647 | the ESP-IDF project, via a configuration server program. 648 | 649 | - `A script for turning on USB-related options 650 | `_, 651 | from the `syzkaller `_ project. 652 | 653 | - `Various automated checks 654 | `_, 655 | including a check for references to undefined Kconfig symbols in source code. 656 | See the ``KconfigCheck`` class. 657 | 658 | - `Various utilities 659 | `_ 660 | from the `ACRN `_ project 661 | 662 | These use the older Kconfiglib 1 API, which was clunkier and not as general 663 | (functions instead of properties, no direct access to the menu structure or 664 | properties, uglier ``__str__()`` output): 665 | 666 | - `genboardscfg.py `_ from `Das U-Boot `_ generates some sort of legacy board database by pulling information from a newly added Kconfig-based configuration system (as far as I understand it :). 667 | 668 | - `gen-manual-lists.py `_ generated listings for an appendix in the `Buildroot `_ manual. (The listing has since been removed.) 669 | 670 | - `gen_kconfig_doc.py `_ from the `esp-idf `_ project generates documentation from Kconfig files. 671 | 672 | - `SConf `_ builds an interactive configuration interface (like ``menuconfig``) on top of Kconfiglib, for use e.g. with `SCons `_. 673 | 674 | - `kconfig-diff.py `_ -- a script by `dubiousjim `_ that compares kernel configurations. 675 | 676 | - Originally, Kconfiglib was used in chapter 4 of my `master's thesis `_ to automatically generate a "minimal" kernel for a given system. Parts of it bother me a bit now, but that's how it goes with old work. 677 | 678 | Sample ``make iscriptconfig`` session 679 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 680 | 681 | The following log should give some idea of the functionality available in the API: 682 | 683 | .. code-block:: 684 | 685 | $ make iscriptconfig 686 | A Kconfig instance 'kconf' for the architecture x86 has been created. 687 | >>> kconf # Calls Kconfig.__repr__() 688 | 689 | >>> kconf.mainmenu_text # Expanded main menu text 690 | 'Linux/x86 4.14.0-rc7 Kernel Configuration' 691 | >>> kconf.top_node # The implicit top-level menu 692 | 693 | >>> kconf.top_node.list # First child menu node 694 | 695 | >>> print(kconf.top_node.list) # Calls MenuNode.__str__() 696 | config SRCARCH 697 | string 698 | option env="SRCARCH" 699 | default "x86" 700 | >>> sym = kconf.top_node.list.next.item # Item contained in next menu node 701 | >>> print(sym) # Calls Symbol.__str__() 702 | config 64BIT 703 | bool "64-bit kernel" if ARCH = "x86" 704 | default ARCH != "i386" 705 | help 706 | Say yes to build a 64-bit kernel - formerly known as x86_64 707 | Say no to build a 32-bit kernel - formerly known as i386 708 | >>> sym # Calls Symbol.__repr__() 709 | 710 | >>> sym.assignable # Currently assignable values (0, 1, 2 = n, m, y) 711 | (0, 2) 712 | >>> sym.set_value(0) # Set it to n 713 | True 714 | >>> sym.tri_value # Check the new value 715 | 0 716 | >>> sym = kconf.syms["X86_MPPARSE"] # Look up symbol by name 717 | >>> print(sym) 718 | config X86_MPPARSE 719 | bool "Enable MPS table" if (ACPI || SFI) && X86_LOCAL_APIC 720 | default y if X86_LOCAL_APIC 721 | help 722 | For old smp systems that do not have proper acpi support. Newer systems 723 | (esp with 64bit cpus) with acpi support, MADT and DSDT will override it 724 | >>> default = sym.defaults[0] # Fetch its first default 725 | >>> sym = default[1] # Fetch the default's condition (just a Symbol here) 726 | >>> print(sym) 727 | config X86_LOCAL_APIC 728 | bool 729 | default y 730 | select IRQ_DOMAIN_HIERARCHY 731 | select PCI_MSI_IRQ_DOMAIN if PCI_MSI 732 | depends on X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_APIC || PCI_MSI 733 | >>> sym.nodes # Show the MenuNode(s) associated with it 734 | [] 735 | >>> kconfiglib.expr_str(sym.defaults[0][1]) # Print the default's condition 736 | 'X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_APIC || PCI_MSI' 737 | >>> kconfiglib.expr_value(sym.defaults[0][1]) # Evaluate it (0 = n) 738 | 0 739 | >>> kconf.syms["64BIT"].set_value(2) 740 | True 741 | >>> kconfiglib.expr_value(sym.defaults[0][1]) # Evaluate it again (2 = y) 742 | 2 743 | >>> kconf.write_config("myconfig") # Save a .config 744 | >>> ^D 745 | $ cat myconfig 746 | # Generated by Kconfiglib (https://github.com/ulfalizer/Kconfiglib) 747 | CONFIG_64BIT=y 748 | CONFIG_X86_64=y 749 | CONFIG_X86=y 750 | CONFIG_INSTRUCTION_DECODER=y 751 | CONFIG_OUTPUT_FORMAT="elf64-x86-64" 752 | CONFIG_ARCH_DEFCONFIG="arch/x86/configs/x86_64_defconfig" 753 | CONFIG_LOCKDEP_SUPPORT=y 754 | CONFIG_STACKTRACE_SUPPORT=y 755 | CONFIG_MMU=y 756 | ... 757 | 758 | Test suite 759 | ---------- 760 | 761 | The test suite is run with 762 | 763 | .. code:: 764 | 765 | $ python(3) Kconfiglib/testsuite.py 766 | 767 | `pypy `_ works too, and is much speedier for everything except ``allnoconfig.py``/``allnoconfig_simpler.py``/``allyesconfig.py``, where it doesn't have time to warm up since 768 | the scripts are run via ``make scriptconfig``. 769 | 770 | The test suite must be run from the top-level kernel directory. It requires that the 771 | Kconfiglib git repository has been cloned into it and that the makefile patch has been applied. 772 | 773 | To get rid of warnings generated for the kernel ``Kconfig`` files, add ``2>/dev/null`` to the command to 774 | discard ``stderr``. 775 | 776 | **NOTE: Forgetting to apply the Makefile patch will cause some tests that compare generated configurations to fail** 777 | 778 | **NOTE: The test suite overwrites .config in the kernel root, so make sure to back it up.** 779 | 780 | The test suite consists of a set of selftests and a set of compatibility tests that 781 | compare configurations generated by Kconfiglib with 782 | configurations generated by the C tools, for a number of cases. See 783 | `testsuite.py `_ 784 | for the available options. 785 | 786 | The `tests/reltest `_ script runs the test suite 787 | and all the example scripts for both Python 2 and Python 3, verifying that everything works. 788 | 789 | Rarely, the output from the C tools is changed slightly (most recently due to a 790 | `change `_ I added). 791 | If you get test suite failures, try running the test suite again against the 792 | `linux-next tree `_, 793 | which has all the latest changes. I will make it clear if any 794 | non-backwards-compatible changes appear. 795 | 796 | A lot of time is spent waiting around for ``make`` and the C utilities (which need to reparse all the 797 | Kconfig files for each defconfig test). Adding some multiprocessing to the test suite would make sense 798 | too. 799 | 800 | Notes 801 | ----- 802 | 803 | * This is version 2 of Kconfiglib, which is not backwards-compatible with 804 | Kconfiglib 1. A summary of changes between Kconfiglib 1 and Kconfiglib 805 | 2 can be found `here 806 | `__. 807 | 808 | * I sometimes see people add custom output formats, which is pretty 809 | straightforward to do (see the implementations of ``write_autoconf()`` and 810 | ``write_config()`` for a template, and also the documentation of the 811 | ``Symbol.config_string`` property). If you come up with something you think 812 | might be useful to other people, I'm happy to take it in upstream. Batteries 813 | included and all that. 814 | 815 | * Kconfiglib assumes the modules symbol is ``MODULES``, which is backwards-compatible. 816 | A warning is printed by default if ``option modules`` is set on some other symbol. 817 | 818 | Let me know if you need proper ``option modules`` support. It wouldn't be that 819 | hard to add. 820 | 821 | Thanks 822 | ------ 823 | 824 | - To `RomaVis `_, for making 825 | `pymenuconfig `_ and suggesting 826 | the ``rsource`` keyword. 827 | 828 | - To `Mitja Horvat `_, for adding support 829 | for user-defined styles to the terminal menuconfig. 830 | 831 | - To `Philip Craig `_ for adding 832 | support for the ``allnoconfig_y`` option and fixing an obscure issue 833 | with ``comment``\s inside ``choice``\s (that didn't affect correctness but 834 | made outputs differ). ``allnoconfig_y`` is used to force certain symbols 835 | to ``y`` during ``make allnoconfig`` to improve coverage. 836 | 837 | License 838 | ------- 839 | 840 | See `LICENSE.txt `_. SPDX license identifiers are used in the 841 | source code. 842 | -------------------------------------------------------------------------------- /alldefconfig.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2018-2019, Ulf Magnusson 4 | # SPDX-License-Identifier: ISC 5 | 6 | """ 7 | Writes a configuration file where all symbols are set to their their default 8 | values. 9 | 10 | The default output filename is '.config'. A different filename can be passed in 11 | the KCONFIG_CONFIG environment variable. 12 | 13 | Usage for the Linux kernel: 14 | 15 | $ make [ARCH=] scriptconfig SCRIPT=Kconfiglib/alldefconfig.py 16 | """ 17 | import kconfiglib 18 | 19 | 20 | def main(): 21 | kconf = kconfiglib.standard_kconfig(__doc__) 22 | kconf.load_allconfig("alldef.config") 23 | print(kconf.write_config()) 24 | 25 | 26 | if __name__ == "__main__": 27 | main() 28 | -------------------------------------------------------------------------------- /allmodconfig.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2018-2019, Ulf Magnusson 4 | # SPDX-License-Identifier: ISC 5 | 6 | """ 7 | Writes a configuration file where as many symbols as possible are set to 'm'. 8 | 9 | The default output filename is '.config'. A different filename can be passed 10 | in the KCONFIG_CONFIG environment variable. 11 | 12 | Usage for the Linux kernel: 13 | 14 | $ make [ARCH=] scriptconfig SCRIPT=Kconfiglib/allmodconfig.py 15 | """ 16 | import kconfiglib 17 | 18 | 19 | def main(): 20 | kconf = kconfiglib.standard_kconfig(__doc__) 21 | 22 | # See allnoconfig.py 23 | kconf.warn = False 24 | 25 | for sym in kconf.unique_defined_syms: 26 | if sym.orig_type == kconfiglib.BOOL: 27 | # 'bool' choice symbols get their default value, as determined by 28 | # e.g. 'default's on the choice 29 | if not sym.choice: 30 | # All other bool symbols get set to 'y', like for allyesconfig 31 | sym.set_value(2) 32 | elif sym.orig_type == kconfiglib.TRISTATE: 33 | sym.set_value(1) 34 | 35 | for choice in kconf.unique_choices: 36 | choice.set_value(2 if choice.orig_type == kconfiglib.BOOL else 1) 37 | 38 | kconf.warn = True 39 | 40 | kconf.load_allconfig("allmod.config") 41 | 42 | print(kconf.write_config()) 43 | 44 | 45 | if __name__ == "__main__": 46 | main() 47 | -------------------------------------------------------------------------------- /allnoconfig.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2018-2019, Ulf Magnusson 4 | # SPDX-License-Identifier: ISC 5 | 6 | """ 7 | Writes a configuration file where as many symbols as possible are set to 'n'. 8 | 9 | The default output filename is '.config'. A different filename can be passed 10 | in the KCONFIG_CONFIG environment variable. 11 | 12 | Usage for the Linux kernel: 13 | 14 | $ make [ARCH=] scriptconfig SCRIPT=Kconfiglib/allnoconfig.py 15 | """ 16 | 17 | # See examples/allnoconfig_walk.py for another way to implement this script 18 | 19 | import kconfiglib 20 | 21 | 22 | def main(): 23 | kconf = kconfiglib.standard_kconfig(__doc__) 24 | 25 | # Avoid warnings that would otherwise get printed by Kconfiglib for the 26 | # following: 27 | # 28 | # 1. Assigning a value to a symbol without a prompt, which never has any 29 | # effect 30 | # 31 | # 2. Assigning values invalid for the type (only bool/tristate symbols 32 | # accept 0/1/2, for n/m/y). The assignments will be ignored for other 33 | # symbol types, which is what we want. 34 | kconf.warn = False 35 | for sym in kconf.unique_defined_syms: 36 | sym.set_value(2 if sym.is_allnoconfig_y else 0) 37 | kconf.warn = True 38 | 39 | kconf.load_allconfig("allno.config") 40 | 41 | print(kconf.write_config()) 42 | 43 | 44 | if __name__ == "__main__": 45 | main() 46 | -------------------------------------------------------------------------------- /allyesconfig.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2018-2019, Ulf Magnusson 4 | # SPDX-License-Identifier: ISC 5 | 6 | """ 7 | Writes a configuration file where as many symbols as possible are set to 'y'. 8 | 9 | The default output filename is '.config'. A different filename can be passed 10 | in the KCONFIG_CONFIG environment variable. 11 | 12 | Usage for the Linux kernel: 13 | 14 | $ make [ARCH=] scriptconfig SCRIPT=Kconfiglib/allyesconfig.py 15 | """ 16 | import kconfiglib 17 | 18 | 19 | def main(): 20 | kconf = kconfiglib.standard_kconfig(__doc__) 21 | 22 | # See allnoconfig.py 23 | kconf.warn = False 24 | 25 | # Try to set all symbols to 'y'. Dependencies might truncate the value down 26 | # later, but this will at least give the highest possible value. 27 | # 28 | # Assigning 0/1/2 to non-bool/tristate symbols has no effect (int/hex 29 | # symbols still take a string, because they preserve formatting). 30 | for sym in kconf.unique_defined_syms: 31 | # Set choice symbols to 'm'. This value will be ignored for choices in 32 | # 'y' mode (the "normal" mode), which will instead just get their 33 | # default selection, but will set all symbols in m-mode choices to 'm', 34 | # which is as high as they can go. 35 | # 36 | # Here's a convoluted example of how you might get an m-mode choice 37 | # even during allyesconfig: 38 | # 39 | # choice 40 | # tristate "weird choice" 41 | # depends on m 42 | sym.set_value(1 if sym.choice else 2) 43 | 44 | # Set all choices to the highest possible mode 45 | for choice in kconf.unique_choices: 46 | choice.set_value(2) 47 | 48 | kconf.warn = True 49 | 50 | kconf.load_allconfig("allyes.config") 51 | 52 | print(kconf.write_config()) 53 | 54 | 55 | if __name__ == "__main__": 56 | main() 57 | -------------------------------------------------------------------------------- /defconfig.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2019, Ulf Magnusson 4 | # SPDX-License-Identifier: ISC 5 | 6 | """ 7 | Reads a specified configuration file, then writes a new configuration file. 8 | This can be used to initialize the configuration from e.g. an arch-specific 9 | configuration file. This input configuration file would usually be a minimal 10 | configuration file, as generated by e.g. savedefconfig. 11 | 12 | The default output filename is '.config'. A different filename can be passed in 13 | the KCONFIG_CONFIG environment variable. 14 | """ 15 | import argparse 16 | 17 | import kconfiglib 18 | 19 | 20 | def main(): 21 | parser = argparse.ArgumentParser( 22 | formatter_class=argparse.RawDescriptionHelpFormatter, 23 | description=__doc__) 24 | 25 | parser.add_argument( 26 | "--kconfig", 27 | default="Kconfig", 28 | help="Top-level Kconfig file (default: Kconfig)") 29 | 30 | parser.add_argument( 31 | "config", 32 | metavar="CONFIGURATION", 33 | help="Input configuration file") 34 | 35 | args = parser.parse_args() 36 | 37 | kconf = kconfiglib.Kconfig(args.kconfig, suppress_traceback=True) 38 | print(kconf.load_config(args.config)) 39 | print(kconf.write_config()) 40 | 41 | 42 | if __name__ == "__main__": 43 | main() 44 | -------------------------------------------------------------------------------- /examples/Kmenuconfig: -------------------------------------------------------------------------------- 1 | mainmenu "Example Kconfig configuration" 2 | 3 | config MODULES 4 | bool "Enable loadable module support" 5 | option modules 6 | default y 7 | 8 | menu "Bool and tristate symbols" 9 | 10 | config BOOL 11 | bool "Bool symbol" 12 | default y 13 | 14 | config BOOL_DEP 15 | bool "Dependent bool symbol" 16 | depends on BOOL 17 | 18 | # Mix it up a bit with an 'if' instead of a 'depends on' 19 | if BOOL 20 | 21 | config TRI_DEP 22 | tristate "Dependent tristate symbol" 23 | select SELECTED_BY_TRI_DEP 24 | imply IMPLIED_BY_TRI_DEP 25 | 26 | endif 27 | 28 | config TWO_MENU_NODES 29 | bool "First prompt" 30 | depends on BOOL 31 | 32 | config TRI 33 | tristate "Tristate symbol" 34 | 35 | config TWO_MENU_NODES 36 | bool "Second prompt" 37 | 38 | comment "These are selected by TRI_DEP" 39 | 40 | config SELECTED_BY_TRI_DEP 41 | tristate "Tristate selected by TRI_DEP" 42 | 43 | config IMPLIED_BY_TRI_DEP 44 | tristate "Tristate implied by TRI_DEP" 45 | 46 | endmenu 47 | 48 | 49 | menu "String, int, and hex symbols" 50 | 51 | config STRING 52 | string "String symbol" 53 | default "foo" 54 | 55 | config INT 56 | int "Int symbol" 57 | default 747 58 | 59 | config HEX 60 | hex "Hex symbol" 61 | default 0xABC 62 | 63 | endmenu 64 | 65 | 66 | menu "Various choices" 67 | 68 | choice BOOL_CHOICE 69 | bool "Bool choice" 70 | 71 | config BOOL_CHOICE_SYM_1 72 | bool "Bool choice sym 1" 73 | 74 | config BOOL_CHOICE_SYM_2 75 | bool "Bool choice sym 2" 76 | 77 | endchoice 78 | 79 | choice TRI_CHOICE 80 | tristate "Tristate choice" 81 | 82 | config TRI_CHOICE_SYM_1 83 | tristate "Tristate choice sym 1" 84 | 85 | config TRI_CHOICE_SYM_2 86 | tristate "Tristate choice sym 2" 87 | 88 | endchoice 89 | 90 | choice OPT_BOOL_CHOICE 91 | bool "Optional bool choice" 92 | optional 93 | 94 | config OPT_BOOL_CHOICE_SYM_1 95 | bool "Optional bool choice sym 1" 96 | 97 | config OPT_BOOL_CHOICE_SYM_2 98 | bool "Optional bool choice sym 2" 99 | 100 | endchoice 101 | 102 | endmenu 103 | -------------------------------------------------------------------------------- /examples/allnoconfig_walk.py: -------------------------------------------------------------------------------- 1 | # This is tree-walking version of allnoconfig.py, for demonstration purposes. 2 | # Verified by the test suite to generate identical output to 'make allnoconfig' 3 | # for all ARCHes. 4 | # 5 | # Note: A more practical version would use Kconfig.node_iter(). The manual tree 6 | # walking is for demonstration purposes. 7 | # 8 | # Usage for the Linux kernel: 9 | # 10 | # $ make [ARCH=] scriptconfig SCRIPT=Kconfiglib/examples/allnoconfig_walk.py 11 | 12 | import sys 13 | 14 | from kconfiglib import Kconfig, Symbol 15 | 16 | 17 | def do_allnoconfig(node): 18 | global changed 19 | 20 | # Walk the tree of menu nodes. You can imagine this as going down/into menu 21 | # entries in the menuconfig interface, setting each to n (or the lowest 22 | # assignable value). 23 | 24 | while node: 25 | if isinstance(node.item, Symbol): 26 | sym = node.item 27 | 28 | # Is the symbol a non-allnoconfig_y symbol that can be set to a 29 | # lower value than its current value? 30 | if (not sym.is_allnoconfig_y and 31 | sym.assignable and 32 | sym.assignable[0] < sym.tri_value): 33 | 34 | # Yup, lower it 35 | sym.set_value(sym.assignable[0]) 36 | changed = True 37 | 38 | # Recursively lower children 39 | if node.list: 40 | do_allnoconfig(node.list) 41 | 42 | node = node.next 43 | 44 | 45 | # Parse the Kconfig files 46 | kconf = Kconfig(sys.argv[1]) 47 | 48 | # Do an initial pass to set 'option allnoconfig_y' symbols to y 49 | for sym in kconf.unique_defined_syms: 50 | if sym.is_allnoconfig_y: 51 | sym.set_value(2) 52 | 53 | while True: 54 | # Changing later symbols in the configuration can sometimes allow earlier 55 | # symbols to be lowered, e.g. if a later symbol 'select's an earlier 56 | # symbol. To handle such situations, we do additional passes over the tree 57 | # until we're no longer able to change the value of any symbol in a pass. 58 | changed = False 59 | 60 | do_allnoconfig(kconf.top_node) 61 | 62 | # Did the pass change any symbols? 63 | if not changed: 64 | break 65 | 66 | print(kconf.write_config()) 67 | -------------------------------------------------------------------------------- /examples/defconfig_oldconfig.py: -------------------------------------------------------------------------------- 1 | # Produces exactly the same output as the following script: 2 | # 3 | # make defconfig 4 | # echo CONFIG_ETHERNET=n >> .config 5 | # make oldconfig 6 | # echo CONFIG_ETHERNET=y >> .config 7 | # yes n | make oldconfig 8 | # 9 | # This came up in https://github.com/ulfalizer/Kconfiglib/issues/15. 10 | # 11 | # Usage: 12 | # 13 | # $ make [ARCH=] scriptconfig SCRIPT=Kconfiglib/examples/defconfig_oldconfig.py 14 | 15 | import sys 16 | 17 | import kconfiglib 18 | 19 | 20 | kconf = kconfiglib.Kconfig(sys.argv[1]) 21 | 22 | # Mirrors defconfig 23 | kconf.load_config("arch/x86/configs/x86_64_defconfig") 24 | kconf.write_config() 25 | 26 | # Mirrors the first oldconfig 27 | kconf.load_config() 28 | kconf.syms["ETHERNET"].set_value(0) 29 | kconf.write_config() 30 | 31 | # Mirrors the second oldconfig 32 | kconf.load_config() 33 | kconf.syms["ETHERNET"].set_value(2) 34 | for s in kconf.unique_defined_syms: 35 | if s.user_value is None and 0 in s.assignable: 36 | s.set_value(0) 37 | 38 | # Write the final configuration 39 | print(kconf.write_config()) 40 | -------------------------------------------------------------------------------- /examples/dumpvars.py: -------------------------------------------------------------------------------- 1 | # Prints all (set) environment variables referenced in the Kconfig files 2 | # together with their values, as a list of assignments. 3 | # 4 | # Note: This only works for environment variables referenced via the $(FOO) 5 | # preprocessor syntax. The older $FOO syntax is maintained for backwards 6 | # compatibility. 7 | 8 | import os 9 | import sys 10 | 11 | import kconfiglib 12 | 13 | 14 | print(" ".join("{}='{}'".format(var, os.environ[var]) 15 | for var in kconfiglib.Kconfig(sys.argv[1]).env_vars)) 16 | -------------------------------------------------------------------------------- /examples/eval_expr.py: -------------------------------------------------------------------------------- 1 | # Evaluates an expression (e.g. "X86_64 || (X86_32 && X86_LOCAL_APIC)") in the 2 | # context of a configuration. Note that this always yields a tristate value (n, 3 | # m, or y). 4 | # 5 | # Usage: 6 | # 7 | # $ make [ARCH=] scriptconfig SCRIPT=Kconfiglib/examples/eval_expr.py SCRIPT_ARG= 8 | 9 | import sys 10 | 11 | import kconfiglib 12 | 13 | 14 | if len(sys.argv) < 3: 15 | sys.exit("Pass the expression to evaluate with SCRIPT_ARG=") 16 | 17 | kconf = kconfiglib.Kconfig(sys.argv[1]) 18 | expr = sys.argv[2] 19 | 20 | # Enable modules so that m doesn't get demoted to n 21 | kconf.modules.set_value(2) 22 | 23 | print("the expression '{}' evaluates to {}" 24 | .format(expr, kconf.eval_string(expr))) 25 | -------------------------------------------------------------------------------- /examples/find_symbol.py: -------------------------------------------------------------------------------- 1 | # Prints all menu nodes that reference a given symbol any of their properties 2 | # or property conditions, along with their parent menu nodes. 3 | # 4 | # Usage: 5 | # 6 | # $ make [ARCH=] scriptconfig SCRIPT=Kconfiglib/examples/find_symbol.py SCRIPT_ARG= 7 | # 8 | # Example output for SCRIPT_ARG=X86: 9 | # 10 | # Found 470 locations that reference X86: 11 | # 12 | # ========== Location 1 (init/Kconfig:1108) ========== 13 | # 14 | # config SGETMASK_SYSCALL 15 | # bool 16 | # prompt "sgetmask/ssetmask syscalls support" if EXPERT 17 | # default PARISC || M68K || PPC || MIPS || X86 || SPARC || MICROBLAZE || SUPERH 18 | # help 19 | # sys_sgetmask and sys_ssetmask are obsolete system calls 20 | # no longer supported in libc but still enabled by default in some 21 | # architectures. 22 | # 23 | # If unsure, leave the default option here. 24 | # 25 | # ---------- Parent 1 (init/Kconfig:1077) ---------- 26 | # 27 | # menuconfig EXPERT 28 | # bool 29 | # prompt "Configure standard kernel features (expert users)" 30 | # select DEBUG_KERNEL 31 | # help 32 | # This option allows certain base kernel options and settings 33 | # to be disabled or tweaked. This is for specialized 34 | # environments which can tolerate a "non-standard" kernel. 35 | # Only use this if you really know what you are doing. 36 | # 37 | # ---------- Parent 2 (init/Kconfig:39) ---------- 38 | # 39 | # menu "General setup" 40 | # 41 | # ========== Location 2 (arch/Kconfig:29) ========== 42 | # 43 | # config OPROFILE_EVENT_MULTIPLEX 44 | # bool 45 | # prompt "OProfile multiplexing support (EXPERIMENTAL)" 46 | # default "n" 47 | # depends on OPROFILE && X86 48 | # help 49 | # The number of hardware counters is limited. The multiplexing 50 | # feature enables OProfile to gather more events than counters 51 | # are provided by the hardware. This is realized by switching 52 | # between events at a user specified time interval. 53 | # 54 | # If unsure, say N. 55 | # 56 | # ---------- Parent 1 (arch/Kconfig:16) ---------- 57 | # 58 | # config OPROFILE 59 | # tristate 60 | # prompt "OProfile system profiling" 61 | # select RING_BUFFER 62 | # select RING_BUFFER_ALLOW_SWAP 63 | # depends on PROFILING && HAVE_OPROFILE 64 | # help 65 | # OProfile is a profiling system capable of profiling the 66 | # whole system, include the kernel, kernel modules, libraries, 67 | # and applications. 68 | # 69 | # If unsure, say N. 70 | # 71 | # ---------- Parent 2 (init/Kconfig:39) ---------- 72 | # 73 | # menu "General setup" 74 | # 75 | # ... (tons more) 76 | 77 | import sys 78 | 79 | import kconfiglib 80 | 81 | 82 | if len(sys.argv) < 3: 83 | sys.exit('Pass symbol name (without "CONFIG_" prefix) with SCRIPT_ARG=') 84 | 85 | kconf = kconfiglib.Kconfig(sys.argv[1]) 86 | sym_name = sys.argv[2] 87 | if sym_name not in kconf.syms: 88 | print("No symbol {} exists in the configuration".format(sym_name)) 89 | sys.exit(0) 90 | 91 | referencing = [node for node in kconf.node_iter() 92 | if kconf.syms[sym_name] in node.referenced] 93 | if not referencing: 94 | print("No references to {} found".format(sym_name)) 95 | sys.exit(0) 96 | 97 | print("Found {} locations that reference {}:\n" 98 | .format(len(referencing), sym_name)) 99 | 100 | for i, node in enumerate(referencing, 1): 101 | print("========== Location {} ({}:{}) ==========\n\n{}" 102 | .format(i, node.filename, node.linenr, node)) 103 | 104 | # Print the parents of the menu node too 105 | 106 | node = node.parent 107 | parent_i = 1 108 | while node is not kconf.top_node: 109 | print("---------- Parent {} ({}:{}) ----------\n\n{}" 110 | .format(parent_i, node.filename, node.linenr, node)) 111 | node = node.parent 112 | parent_i += 1 113 | -------------------------------------------------------------------------------- /examples/help_grep.py: -------------------------------------------------------------------------------- 1 | # Does a case-insensitive search for a regular expression in the help texts of 2 | # symbols and choices and the prompts of menus and comments. Prints the 3 | # matching items together with their locations and the matching text. 4 | # 5 | # Usage: 6 | # 7 | # $ make [ARCH=] scriptconfig SCRIPT=Kconfiglib/examples/help_grep.py SCRIPT_ARG= 8 | # 9 | # Shortened example output for SCRIPT_ARG=general: 10 | # 11 | # menu "General setup" 12 | # location: init/Kconfig:39 13 | # 14 | # config SYSVIPC 15 | # bool 16 | # prompt "System V IPC" 17 | # help 18 | # ... 19 | # exchange information. It is generally considered to be a good thing, 20 | # ... 21 | # 22 | # location: init/Kconfig:233 23 | # 24 | # config BSD_PROCESS_ACCT 25 | # bool 26 | # prompt "BSD Process Accounting" if MULTIUSER 27 | # help 28 | # ... 29 | # information. This is generally a good idea, so say Y. 30 | # 31 | # location: init/Kconfig:403 32 | # 33 | # ... 34 | 35 | 36 | import re 37 | import sys 38 | 39 | from kconfiglib import Kconfig, Symbol, Choice, MENU, COMMENT 40 | 41 | 42 | if len(sys.argv) < 3: 43 | sys.exit("Pass the regex with SCRIPT_ARG=") 44 | 45 | search = re.compile(sys.argv[2], re.IGNORECASE).search 46 | 47 | for node in Kconfig(sys.argv[1]).node_iter(): 48 | match = False 49 | 50 | if isinstance(node.item, (Symbol, Choice)) and \ 51 | node.help is not None and search(node.help): 52 | print(node.item) 53 | match = True 54 | 55 | elif node.item == MENU and search(node.prompt[0]): 56 | print('menu "{}"'.format(node.prompt[0])) 57 | match = True 58 | 59 | elif node.item == COMMENT and search(node.prompt[0]): 60 | print('comment "{}"'.format(node.prompt[0])) 61 | match = True 62 | 63 | if match: 64 | print("location: {}:{}\n".format(node.filename, node.linenr)) 65 | -------------------------------------------------------------------------------- /examples/kconfiglib.py: -------------------------------------------------------------------------------- 1 | ../kconfiglib.py -------------------------------------------------------------------------------- /examples/list_undefined.py: -------------------------------------------------------------------------------- 1 | # Prints a list of symbols that are referenced in the Kconfig files of some 2 | # architecture but not defined by the Kconfig files of any architecture. 3 | # 4 | # A Kconfig file might be shared between many architectures and legitimately 5 | # reference undefined symbols for some of them, but if no architecture defines 6 | # the symbol, it usually indicates a problem or potential cleanup. 7 | # 8 | # This script could be sped up a lot if needed. See the comment near the 9 | # referencing_nodes() call. 10 | # 11 | # Run with the following command in the kernel root: 12 | # 13 | # $ python(3) Kconfiglib/examples/list_undefined.py 14 | # 15 | # Example output: 16 | # 17 | # Registering defined and undefined symbols for all arches 18 | # Processing mips 19 | # Processing ia64 20 | # Processing metag 21 | # ... 22 | # 23 | # Finding references to each undefined symbol 24 | # Processing mips 25 | # Processing ia64 26 | # Processing metag 27 | # ... 28 | # 29 | # The following globally undefined symbols were found, listed here 30 | # together with the locations of the items that reference them. 31 | # References might come from enclosing menus and ifs. 32 | # 33 | # ARM_ERRATA_753970: arch/arm/mach-mvebu/Kconfig:56, arch/arm/mach-mvebu/Kconfig:39 34 | # SUNXI_CCU_MP: drivers/clk/sunxi-ng/Kconfig:14 35 | # SUNXI_CCU_DIV: drivers/clk/sunxi-ng/Kconfig:14 36 | # AC97: sound/ac97/Kconfig:6 37 | # ... 38 | 39 | import os 40 | import subprocess 41 | 42 | from kconfiglib import Kconfig 43 | 44 | 45 | # Referenced inside the Kconfig files 46 | os.environ["KERNELVERSION"] = str( 47 | subprocess.check_output(("make", "kernelversion")).decode("utf-8").rstrip() 48 | ) 49 | 50 | 51 | def all_arch_srcarch_pairs(): 52 | """ 53 | Generates all valid (ARCH, SRCARCH) tuples for the kernel, corresponding to 54 | different architectures. SRCARCH holds the arch/ subdirectory. 55 | """ 56 | for srcarch in os.listdir("arch"): 57 | # Each subdirectory of arch/ containing a Kconfig file corresponds to 58 | # an architecture 59 | if os.path.exists(os.path.join("arch", srcarch, "Kconfig")): 60 | yield (srcarch, srcarch) 61 | 62 | # Some architectures define additional ARCH settings with ARCH != SRCARCH 63 | # (search for "Additional ARCH settings for" in the top-level Makefile) 64 | 65 | yield ("i386", "x86") 66 | yield ("x86_64", "x86") 67 | 68 | yield ("sparc32", "sparc") 69 | yield ("sparc64", "sparc") 70 | 71 | yield ("sh64", "sh") 72 | 73 | yield ("um", "um") 74 | 75 | 76 | def all_arch_srcarch_kconfigs(): 77 | """ 78 | Generates Kconfig instances for all the architectures in the kernel 79 | """ 80 | 81 | os.environ["srctree"] = "." 82 | os.environ["HOSTCC"] = "gcc" 83 | os.environ["HOSTCXX"] = "g++" 84 | os.environ["CC"] = "gcc" 85 | os.environ["LD"] = "ld" 86 | 87 | for arch, srcarch in all_arch_srcarch_pairs(): 88 | print(" Processing " + arch) 89 | 90 | os.environ["ARCH"] = arch 91 | os.environ["SRCARCH"] = srcarch 92 | 93 | # um (User Mode Linux) uses a different base Kconfig file 94 | yield Kconfig("Kconfig" if arch != "um" else "arch/x86/um/Kconfig", 95 | warn=False) 96 | 97 | 98 | print("Registering defined and undefined symbols for all arches") 99 | 100 | # Sets holding the names of all defined and undefined symbols, for all 101 | # architectures 102 | defined = set() 103 | undefined = set() 104 | 105 | for kconf in all_arch_srcarch_kconfigs(): 106 | for name, sym in kconf.syms.items(): 107 | if sym.nodes: 108 | # If the symbol has a menu node, it is defined 109 | defined.add(name) 110 | else: 111 | # Undefined symbol. We skip some of the uninteresting ones. 112 | 113 | # Due to how Kconfig works, integer literals show up as symbols 114 | # (from e.g. 'default 1'). Skip those. 115 | try: 116 | int(name, 0) 117 | continue 118 | except ValueError: 119 | # Interesting undefined symbol 120 | undefined.add(name) 121 | 122 | 123 | print("\nFinding references to each undefined symbol") 124 | 125 | def referencing_nodes(kconf, name): 126 | # Returns a list of all menu nodes that reference a symbol named 'name' in 127 | # any of their properties or property conditions 128 | res = [] 129 | 130 | for node in kconf.node_iter(): 131 | for ref in node.referenced: 132 | if ref.name == name: 133 | res.append(node) 134 | 135 | return res 136 | 137 | 138 | # Maps each globally undefined symbol to the menu nodes that reference it 139 | undef_sym_refs = [(name, set()) for name in undefined - defined] 140 | 141 | for kconf in all_arch_srcarch_kconfigs(): 142 | for name, refs in undef_sym_refs: 143 | # This means that we search the entire configuration tree for each 144 | # undefined symbol, which is terribly inefficient. We could speed 145 | # things up by tweaking referencing_nodes() to compare each symbol to 146 | # multiple symbols while walking the configuration tree. 147 | for node in referencing_nodes(kconf, name): 148 | refs.add("{}:{}".format(node.filename, node.linenr)) 149 | 150 | 151 | print("\nThe following globally undefined symbols were found, listed here\n" 152 | "together with the locations of the items that reference them.\n" 153 | "References might come from enclosing menus and ifs.\n") 154 | 155 | for name, refs in undef_sym_refs: 156 | print(" {}: {}".format(name, ", ".join(refs))) 157 | -------------------------------------------------------------------------------- /examples/menuconfig_example.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Implements a simple configuration interface on top of Kconfiglib to 4 | # demonstrate concepts for building a menuconfig-like. Emulates how the 5 | # standard menuconfig prints menu entries. 6 | # 7 | # Always displays the entire Kconfig tree to keep things as simple as possible 8 | # (all symbols, choices, menus, and comments). 9 | # 10 | # Usage: 11 | # 12 | # $ python(3) Kconfiglib/examples/menuconfig.py 13 | # 14 | # A sample Kconfig is available in Kconfiglib/examples/Kmenuconfig. 15 | # 16 | # Here's a notation guide. The notation matches the one used by menuconfig 17 | # (scripts/kconfig/mconf): 18 | # 19 | # [ ] prompt - Bool 20 | # < > prompt - Tristate 21 | # {M} prompt - Tristate selected to m. Can only be set to m or y. 22 | # -*- prompt - Bool/tristate selected to y, pinning it 23 | # -M- prompt - Tristate selected to m that also has m visibility, 24 | # pinning it to m 25 | # (foo) prompt - String/int/hex symbol with value "foo" 26 | # --> prompt - The selected symbol in a choice in y mode. This 27 | # syntax is unique to this example. 28 | # 29 | # When modules are disabled, the .type attribute of TRISTATE symbols and 30 | # choices automatically changes to BOOL. This trick is used by the C 31 | # implementation as well, and gives the expected behavior without having to do 32 | # anything extra here. The original type is available in .orig_type if needed. 33 | # 34 | # The Kconfiglib/examples/Kmenuconfig example uses named choices to be able to 35 | # refer to choices by name. Named choices are supported in the C tools too, but 36 | # I don't think I've ever seen them used in the wild. 37 | # 38 | # Sample session: 39 | # 40 | # $ python Kconfiglib/examples/menuconfig.py Kconfiglib/examples/Kmenuconfig 41 | # 42 | # ======== Example Kconfig configuration ======== 43 | # 44 | # [*] Enable loadable module support (MODULES) 45 | # Bool and tristate symbols 46 | # [*] Bool symbol (BOOL) 47 | # [ ] Dependent bool symbol (BOOL_DEP) 48 | # < > Dependent tristate symbol (TRI_DEP) 49 | # [ ] First prompt (TWO_MENU_NODES) 50 | # < > Tristate symbol (TRI) 51 | # [ ] Second prompt (TWO_MENU_NODES) 52 | # *** These are selected by TRI_DEP *** 53 | # < > Tristate selected by TRI_DEP (SELECTED_BY_TRI_DEP) 54 | # < > Tristate implied by TRI_DEP (IMPLIED_BY_TRI_DEP) 55 | # String, int, and hex symbols 56 | # (foo) String symbol (STRING) 57 | # (747) Int symbol (INT) 58 | # (0xABC) Hex symbol (HEX) 59 | # Various choices 60 | # -*- Bool choice (BOOL_CHOICE) 61 | # --> Bool choice sym 1 (BOOL_CHOICE_SYM_1) 62 | # Bool choice sym 2 (BOOL_CHOICE_SYM_2) 63 | # {M} Tristate choice (TRI_CHOICE) 64 | # < > Tristate choice sym 1 (TRI_CHOICE_SYM_1) 65 | # < > Tristate choice sym 2 (TRI_CHOICE_SYM_2) 66 | # [ ] Optional bool choice (OPT_BOOL_CHOICE) 67 | # 68 | # Enter a symbol/choice name, "load_config", or "write_config" (or press CTRL+D to exit): BOOL 69 | # Value for BOOL (available: n, y): n 70 | # 71 | # ======== Example Kconfig configuration ======== 72 | # 73 | # [*] Enable loadable module support (MODULES) 74 | # Bool and tristate symbols 75 | # [ ] Bool symbol (BOOL) 76 | # < > Tristate symbol (TRI) 77 | # [ ] Second prompt (TWO_MENU_NODES) 78 | # *** These are selected by TRI_DEP *** 79 | # < > Tristate selected by TRI_DEP (SELECTED_BY_TRI_DEP) 80 | # < > Tristate implied by TRI_DEP (IMPLIED_BY_TRI_DEP) 81 | # String, int, and hex symbols 82 | # (foo) String symbol (STRING) 83 | # (747) Int symbol (INT) 84 | # (0xABC) Hex symbol (HEX) 85 | # Various choices 86 | # -*- Bool choice (BOOL_CHOICE) 87 | # --> Bool choice sym 1 (BOOL_CHOICE_SYM_1) 88 | # Bool choice sym 2 (BOOL_CHOICE_SYM_2) 89 | # {M} Tristate choice (TRI_CHOICE) 90 | # < > Tristate choice sym 1 (TRI_CHOICE_SYM_1) 91 | # < > Tristate choice sym 2 (TRI_CHOICE_SYM_2) 92 | # [ ] Optional bool choice (OPT_BOOL_CHOICE) 93 | # 94 | # Enter a symbol/choice name, "load_config", or "write_config" (or press CTRL+D to exit): MODULES 95 | # Value for MODULES (available: n, y): n 96 | # 97 | # ======== Example Kconfig configuration ======== 98 | # 99 | # [ ] Enable loadable module support (MODULES) 100 | # Bool and tristate symbols 101 | # [ ] Bool symbol (BOOL) 102 | # [ ] Tristate symbol (TRI) 103 | # [ ] Second prompt (TWO_MENU_NODES) 104 | # *** These are selected by TRI_DEP *** 105 | # [ ] Tristate selected by TRI_DEP (SELECTED_BY_TRI_DEP) 106 | # [ ] Tristate implied by TRI_DEP (IMPLIED_BY_TRI_DEP) 107 | # String, int, and hex symbols 108 | # (foo) String symbol (STRING) 109 | # (747) Int symbol (INT) 110 | # (0xABC) Hex symbol (HEX) 111 | # Various choices 112 | # -*- Bool choice (BOOL_CHOICE) 113 | # --> Bool choice sym 1 (BOOL_CHOICE_SYM_1) 114 | # Bool choice sym 2 (BOOL_CHOICE_SYM_2) 115 | # -*- Tristate choice (TRI_CHOICE) 116 | # --> Tristate choice sym 1 (TRI_CHOICE_SYM_1) 117 | # Tristate choice sym 2 (TRI_CHOICE_SYM_2) 118 | # [ ] Optional bool choice (OPT_BOOL_CHOICE) 119 | # 120 | # Enter a symbol/choice name, "load_config", or "write_config" (or press CTRL+D to exit): ^D 121 | 122 | from __future__ import print_function 123 | import readline 124 | import sys 125 | 126 | from kconfiglib import Kconfig, \ 127 | Symbol, MENU, COMMENT, \ 128 | BOOL, TRISTATE, STRING, INT, HEX, UNKNOWN, \ 129 | expr_value, \ 130 | TRI_TO_STR 131 | 132 | 133 | # Python 2/3 compatibility hack 134 | if sys.version_info[0] < 3: 135 | input = raw_input 136 | 137 | 138 | def indent_print(s, indent): 139 | print(indent*" " + s) 140 | 141 | 142 | def value_str(sc): 143 | """ 144 | Returns the value part ("[*]", "", "(foo)" etc.) of a menu entry. 145 | 146 | sc: Symbol or Choice. 147 | """ 148 | if sc.type in (STRING, INT, HEX): 149 | return "({})".format(sc.str_value) 150 | 151 | # BOOL or TRISTATE 152 | 153 | # The choice mode is an upper bound on the visibility of choice symbols, so 154 | # we can check the choice symbols' own visibility to see if the choice is 155 | # in y mode 156 | if isinstance(sc, Symbol) and sc.choice and sc.visibility == 2: 157 | # For choices in y mode, print '-->' next to the selected symbol 158 | return "-->" if sc.choice.selection is sc else " " 159 | 160 | tri_val_str = (" ", "M", "*")[sc.tri_value] 161 | 162 | if len(sc.assignable) == 1: 163 | # Pinned to a single value 164 | return "-{}-".format(tri_val_str) 165 | 166 | if sc.type == BOOL: 167 | return "[{}]".format(tri_val_str) 168 | 169 | if sc.type == TRISTATE: 170 | if sc.assignable == (1, 2): 171 | # m and y available 172 | return "{" + tri_val_str + "}" # Gets a bit confusing with .format() 173 | return "<{}>".format(tri_val_str) 174 | 175 | 176 | def node_str(node): 177 | """ 178 | Returns the complete menu entry text for a menu node, or "" for invisible 179 | menu nodes. Invisible menu nodes are those that lack a prompt or that do 180 | not have a satisfied prompt condition. 181 | 182 | Example return value: "[*] Bool symbol (BOOL)" 183 | 184 | The symbol name is printed in parentheses to the right of the prompt. This 185 | is so that symbols can easily be referred to in the configuration 186 | interface. 187 | """ 188 | if not node.prompt: 189 | return "" 190 | 191 | # Even for menu nodes for symbols and choices, it's wrong to check 192 | # Symbol.visibility / Choice.visibility here. The reason is that a symbol 193 | # (and a choice, in theory) can be defined in multiple locations, giving it 194 | # multiple menu nodes, which do not necessarily all have the same prompt 195 | # visibility. Symbol.visibility / Choice.visibility is calculated as the OR 196 | # of the visibility of all the prompts. 197 | prompt, prompt_cond = node.prompt 198 | if not expr_value(prompt_cond): 199 | return "" 200 | 201 | if node.item == MENU: 202 | return " " + prompt 203 | 204 | if node.item == COMMENT: 205 | return " *** {} ***".format(prompt) 206 | 207 | # Symbol or Choice 208 | 209 | sc = node.item 210 | 211 | if sc.type == UNKNOWN: 212 | # Skip symbols defined without a type (these are obscure and generate 213 | # a warning) 214 | return "" 215 | 216 | # {:3} sets the field width to three. Gives nice alignment for empty string 217 | # values. 218 | res = "{:3} {}".format(value_str(sc), prompt) 219 | 220 | # Don't print the name for unnamed choices (the normal kind) 221 | if sc.name is not None: 222 | res += " ({})".format(sc.name) 223 | 224 | return res 225 | 226 | 227 | def print_menuconfig_nodes(node, indent): 228 | """ 229 | Prints a tree with all the menu entries rooted at 'node'. Child menu 230 | entries are indented. 231 | """ 232 | while node: 233 | string = node_str(node) 234 | if string: 235 | indent_print(string, indent) 236 | 237 | if node.list: 238 | print_menuconfig_nodes(node.list, indent + 8) 239 | 240 | node = node.next 241 | 242 | 243 | def print_menuconfig(kconf): 244 | """ 245 | Prints all menu entries for the configuration. 246 | """ 247 | # Print the expanded mainmenu text at the top. This is the same as 248 | # kconf.top_node.prompt[0], but with variable references expanded. 249 | print("\n======== {} ========\n".format(kconf.mainmenu_text)) 250 | 251 | print_menuconfig_nodes(kconf.top_node.list, 0) 252 | print("") 253 | 254 | 255 | def get_value_from_user(sc): 256 | """ 257 | Prompts the user for a value for the symbol or choice 'sc'. For 258 | bool/tristate symbols and choices, provides a list of all the assignable 259 | values. 260 | """ 261 | if not sc.visibility: 262 | print(sc.name + " is not currently visible") 263 | return False 264 | 265 | prompt = "Value for {}".format(sc.name) 266 | if sc.type in (BOOL, TRISTATE): 267 | prompt += " (available: {})" \ 268 | .format(", ".join(TRI_TO_STR[val] for val in sc.assignable)) 269 | prompt += ": " 270 | 271 | val = input(prompt) 272 | 273 | # Automatically add a "0x" prefix for hex symbols, like the menuconfig 274 | # interface does. This isn't done when loading .config files, hence why 275 | # set_value() doesn't do it automatically. 276 | if sc.type == HEX and not val.startswith(("0x", "0X")): 277 | val = "0x" + val 278 | 279 | # Let Kconfiglib itself print a warning here if the value is invalid. We 280 | # could also disable warnings temporarily with 'kconf.warn = False' and 281 | # print our own warning. 282 | return sc.set_value(val) 283 | 284 | 285 | if __name__ == "__main__": 286 | if len(sys.argv) != 2: 287 | sys.exit("usage: menuconfig.py ") 288 | 289 | # Load Kconfig configuration files 290 | kconf = Kconfig(sys.argv[1]) 291 | 292 | # Print the initial configuration tree 293 | print_menuconfig(kconf) 294 | 295 | while True: 296 | try: 297 | cmd = input('Enter a symbol/choice name, "load_config", or ' 298 | '"write_config" (or press CTRL+D to exit): ').strip() 299 | except EOFError: 300 | print("") 301 | break 302 | 303 | if cmd == "load_config": 304 | config_filename = input(".config file to load: ") 305 | try: 306 | # Returns a message telling which file got loaded 307 | print(kconf.load_config(config_filename)) 308 | except EnvironmentError as e: 309 | print(e, file=sys.stderr) 310 | 311 | print_menuconfig(kconf) 312 | continue 313 | 314 | if cmd == "write_config": 315 | config_filename = input("To this file: ") 316 | try: 317 | # Returns a message telling which file got saved 318 | print(kconf.write_config(config_filename)) 319 | except EnvironmentError as e: 320 | print(e, file=sys.stderr) 321 | 322 | continue 323 | 324 | # Assume 'cmd' is the name of a symbol or choice if it isn't one of the 325 | # commands above, prompt the user for a value for it, and print the new 326 | # configuration tree 327 | 328 | if cmd in kconf.syms: 329 | if get_value_from_user(kconf.syms[cmd]): 330 | print_menuconfig(kconf) 331 | 332 | continue 333 | 334 | if cmd in kconf.named_choices: 335 | if get_value_from_user(kconf.named_choices[cmd]): 336 | print_menuconfig(kconf) 337 | 338 | continue 339 | 340 | print("No symbol/choice named '{}' in the configuration".format(cmd), 341 | file=sys.stderr) 342 | -------------------------------------------------------------------------------- /examples/merge_config.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # This script functions similarly to scripts/kconfig/merge_config.sh from the 4 | # kernel tree, merging multiple configurations fragments to produce a complete 5 | # .config, with unspecified values filled in as for alldefconfig. 6 | # 7 | # The generated .config respects symbol dependencies, and a warning is printed 8 | # if any symbol gets a different value from the assigned value. 9 | # 10 | # For a real-world merging example based on this script, see 11 | # https://github.com/zephyrproject-rtos/zephyr/blob/master/scripts/kconfig/kconfig.py. 12 | # 13 | # Here's a demo: 14 | # 15 | # Kconfig contents: 16 | # 17 | # config FOO 18 | # bool "FOO" 19 | # 20 | # config BAR 21 | # bool "BAR" 22 | # 23 | # config BAZ 24 | # string "BAZ" 25 | # 26 | # config QAZ 27 | # bool "QAZ" if n 28 | # 29 | # 30 | # conf1 contents: 31 | # 32 | # CONFIG_FOO=y 33 | # 34 | # 35 | # conf2 contents: 36 | # 37 | # CONFIG_BAR=y 38 | # 39 | # 40 | # conf3 contents: 41 | # 42 | # # Assigned twice (would generate warning if 'warn_assign_override' was 43 | # # True) 44 | # # CONFIG_FOO is not set 45 | # 46 | # # Ops... this symbol doesn't exist 47 | # CONFIG_OPS=y 48 | # 49 | # CONFIG_BAZ="baz string" 50 | # 51 | # 52 | # conf4 contents: 53 | # 54 | # CONFIG_QAZ=y 55 | # 56 | # 57 | # Running: 58 | # 59 | # $ python(3) merge_config.py Kconfig merged conf1 conf2 conf3 conf4 60 | # Merged configuration 'conf1' 61 | # Merged configuration 'conf2' 62 | # conf3:5: warning: attempt to assign the value 'y' to the undefined symbol OPS 63 | # Merged configuration 'conf3' 64 | # Merged configuration 'conf4' 65 | # Configuration saved to 'merged' 66 | # warning: QAZ (defined at Kconfig:10) was assigned the value 'y' but got the value 'n' -- check dependencies 67 | # $ cat merged 68 | # Generated by Kconfiglib (https://github.com/ulfalizer/Kconfiglib) 69 | # # CONFIG_FOO is not set 70 | # CONFIG_BAR=y 71 | # CONFIG_BAZ="baz string" 72 | 73 | from __future__ import print_function 74 | import sys 75 | 76 | from kconfiglib import Kconfig, BOOL, TRISTATE, TRI_TO_STR 77 | 78 | 79 | if len(sys.argv) < 4: 80 | sys.exit("usage: merge_config.py Kconfig merged_config config1 [config2 ...]") 81 | 82 | kconf = Kconfig(sys.argv[1], suppress_traceback=True) 83 | 84 | # Enable warnings for assignments to undefined symbols 85 | kconf.warn_assign_undef = True 86 | 87 | # (This script uses alldefconfig as the base. Other starting states could be 88 | # set up here as well. The approach in examples/allnoconfig_simpler.py could 89 | # provide an allnoconfig starting state for example.) 90 | 91 | # Disable warnings generated for multiple assignments to the same symbol within 92 | # a (set of) configuration files. Assigning a symbol multiple times might be 93 | # done intentionally when merging configuration files. 94 | kconf.warn_assign_override = False 95 | kconf.warn_assign_redun = False 96 | 97 | # Create a merged configuration by loading the fragments with replace=False. 98 | # load_config() and write_config() returns a message to print. 99 | for config in sys.argv[3:]: 100 | print(kconf.load_config(config, replace=False)) 101 | 102 | # Write the merged configuration 103 | print(kconf.write_config(sys.argv[2])) 104 | 105 | # Print warnings for symbols whose actual value doesn't match the assigned 106 | # value 107 | for sym in kconf.defined_syms: 108 | # Was the symbol assigned to? 109 | if sym.user_value is not None: 110 | # Tristate values are represented as 0, 1, 2. Having them as 111 | # "n", "m", "y" is more convenient here, so convert. 112 | if sym.type in (BOOL, TRISTATE): 113 | user_value = TRI_TO_STR[sym.user_value] 114 | else: 115 | user_value = sym.user_value 116 | 117 | if user_value != sym.str_value: 118 | print("warning: {} was assigned the value '{}' but got the " 119 | "value '{}' -- check dependencies".format( 120 | sym.name_and_loc, user_value, sym.str_value), 121 | file=sys.stderr) 122 | -------------------------------------------------------------------------------- /examples/print_config_tree.py: -------------------------------------------------------------------------------- 1 | # Prints menu entries as a tree with its value in the .config file. This can be 2 | # handy e.g. for diffing between different .config files or versions of Kconfig files. 3 | # 4 | # Usage: 5 | # 6 | # $ make [ARCH=] scriptconfig SCRIPT=print_config_tree.py [SCRIPT_ARG=<.config>] 7 | # 8 | # If the variable WITH_HELP_DESC is modified to 'True', the help is added 9 | # to the symbols. 10 | # 11 | # Here's a notation guide. The notation matches the one used by menuconfig 12 | # (scripts/kconfig/mconf): 13 | # 14 | # [ ] prompt - Bool 15 | # < > prompt - Tristate 16 | # {M} prompt - Tristate selected to m. Can only be set to m or y. 17 | # -*- prompt - Bool/tristate selected to y, pinning it 18 | # -M- prompt - Tristate selected to m that also has m visibility, 19 | # pinning it to m 20 | # (foo) prompt - String/int/hex symbol with value "foo" 21 | # --> prompt - The selected symbol in a choice in y mode. This 22 | # syntax is unique to this example. 23 | # 24 | # When modules are disabled, the .type attribute of TRISTATE symbols and 25 | # choices automatically changes to BOOL. This trick is used by the C 26 | # implementation as well, and gives the expected behavior without having to do 27 | # anything extra here. The original type is available in .orig_type if needed. 28 | # 29 | # Example output: 30 | # 31 | # $ make scriptconfig SCRIPT=Kconfiglib/examples/print_config_tree.py [SCRIPT_ARG=<.config file>] 32 | # 33 | # ======== Linux/x86 4.9.82 Kernel Configuration ======== 34 | # 35 | # [*] 64-bit kernel (64BIT) 36 | # General setup 37 | # () Cross-compiler tool prefix (CROSS_COMPILE) 38 | # [ ] Compile also drivers which will not load (COMPILE_TEST) 39 | # () Local version - append to kernel release (LOCALVERSION) 40 | # [*] Automatically append version information to the version string (LOCALVERSION_AUTO) 41 | # -*- Kernel compression mode 42 | # ... 43 | # 44 | # With the variable WITH_HELP_DESC modified to 'True': 45 | # 46 | # ======== Linux/x86 4.9.82 Kernel Configuration ======== 47 | # 48 | # [*] 64-bit kernel - Say yes to build a 64-bit kernel - formerly known as x86_64 Say no to build a 32-bit kernel - formerly known as i386 (64BIT) 49 | # General setup 50 | # () Cross-compiler tool prefix - Same as running 'make CROSS_COMPILE=prefix-' but stored for default make runs in this kernel build directory. You don't need to set this unless you want the configured kernel build directory to select the cross-compiler automatically. (CROSS_COMPILE) 51 | # [ ] Compile also drivers which will not load - Some drivers can be compiled on a different platform than they are intended to be run on. Despite they cannot be loaded there (or even when they load they cannot be used due to missing HW support), developers still, opposing to distributors, might want to build such drivers to compile-test them. If you are a developer and want to build everything available, say Y here. If you are a user/distributor, say N here to exclude useless drivers to be distributed. (COMPILE_TEST) 52 | # ... 53 | 54 | import sys 55 | 56 | from kconfiglib import Kconfig, \ 57 | Symbol, MENU, COMMENT, \ 58 | BOOL, TRISTATE, STRING, INT, HEX, UNKNOWN, \ 59 | expr_value 60 | 61 | 62 | # Add help description to output 63 | WITH_HELP_DESC = False 64 | 65 | 66 | def indent_print(s, indent): 67 | print(indent*" " + s) 68 | 69 | 70 | def value_str(sc): 71 | """ 72 | Returns the value part ("[*]", "", "(foo)" etc.) of a menu entry. 73 | 74 | sc: Symbol or Choice. 75 | """ 76 | if sc.type in (STRING, INT, HEX): 77 | return "({})".format(sc.str_value) 78 | 79 | # BOOL or TRISTATE 80 | 81 | # The choice mode is an upper bound on the visibility of choice symbols, so 82 | # we can check the choice symbols' own visibility to see if the choice is 83 | # in y mode 84 | if isinstance(sc, Symbol) and sc.choice and sc.visibility == 2: 85 | # For choices in y mode, print '-->' next to the selected symbol 86 | return "-->" if sc.choice.selection is sc else " " 87 | 88 | tri_val_str = (" ", "M", "*")[sc.tri_value] 89 | 90 | if len(sc.assignable) == 1: 91 | # Pinned to a single value 92 | return "-{}-".format(tri_val_str) 93 | 94 | if sc.type == BOOL: 95 | return "[{}]".format(tri_val_str) 96 | 97 | if sc.type == TRISTATE: 98 | if sc.assignable == (1, 2): 99 | # m and y available 100 | return "{" + tri_val_str + "}" # Gets a bit confusing with .format() 101 | return "<{}>".format(tri_val_str) 102 | 103 | 104 | def node_str(node): 105 | """ 106 | Returns the complete menu entry text for a menu node, or "" for invisible 107 | menu nodes. Invisible menu nodes are those that lack a prompt or that do 108 | not have a satisfied prompt condition. 109 | 110 | Example return value: "[*] Bool symbol (BOOL)" 111 | 112 | The symbol name is printed in parentheses to the right of the prompt. 113 | """ 114 | if not node.prompt: 115 | return "" 116 | 117 | # Even for menu nodes for symbols and choices, it's wrong to check 118 | # Symbol.visibility / Choice.visibility here. The reason is that a symbol 119 | # (and a choice, in theory) can be defined in multiple locations, giving it 120 | # multiple menu nodes, which do not necessarily all have the same prompt 121 | # visibility. Symbol.visibility / Choice.visibility is calculated as the OR 122 | # of the visibility of all the prompts. 123 | prompt, prompt_cond = node.prompt 124 | if not expr_value(prompt_cond): 125 | return "" 126 | 127 | if node.item == MENU: 128 | return " " + prompt 129 | 130 | if node.item == COMMENT: 131 | return " *** {} ***".format(prompt) 132 | 133 | # Symbol or Choice 134 | 135 | sc = node.item 136 | 137 | if sc.type == UNKNOWN: 138 | # Skip symbols defined without a type (these are obscure and generate 139 | # a warning) 140 | return "" 141 | 142 | # Add help text 143 | if WITH_HELP_DESC: 144 | prompt += ' - ' + str(node.help).replace('\n', ' ').replace('\r', '') 145 | 146 | # {:3} sets the field width to three. Gives nice alignment for empty string 147 | # values. 148 | res = "{:3} {}".format(value_str(sc), prompt) 149 | 150 | # Don't print the name for unnamed choices (the normal kind) 151 | if sc.name is not None: 152 | res += " ({})".format(sc.name) 153 | 154 | return res 155 | 156 | 157 | def print_menuconfig_nodes(node, indent): 158 | """ 159 | Prints a tree with all the menu entries rooted at 'node'. Child menu 160 | entries are indented. 161 | """ 162 | while node: 163 | string = node_str(node) 164 | if string: 165 | indent_print(string, indent) 166 | 167 | if node.list: 168 | print_menuconfig_nodes(node.list, indent + 8) 169 | 170 | node = node.next 171 | 172 | 173 | def print_menuconfig(kconf): 174 | """ 175 | Prints all menu entries for the configuration. 176 | """ 177 | # Print the expanded mainmenu text at the top. This is the same as 178 | # kconf.top_node.prompt[0], but with variable references expanded. 179 | print("\n======== {} ========\n".format(kconf.mainmenu_text)) 180 | 181 | print_menuconfig_nodes(kconf.top_node.list, 0) 182 | print("") 183 | 184 | 185 | if __name__ == "__main__": 186 | 187 | # Load Kconfig configuration files 188 | kconf = Kconfig(sys.argv[1]) 189 | 190 | # Set default .config file or load it from argv 191 | if len(sys.argv) == 2: 192 | config_filename = '.config' 193 | else: 194 | config_filename = sys.argv[2] 195 | 196 | kconf.load_config(config_filename) 197 | 198 | # Print the configuration tree 199 | print_menuconfig(kconf) 200 | -------------------------------------------------------------------------------- /examples/print_sym_info.py: -------------------------------------------------------------------------------- 1 | # Loads a Kconfig and a .config and prints a symbol. 2 | # 3 | # Usage: 4 | # 5 | # $ make [ARCH=] scriptconfig SCRIPT=Kconfiglib/examples/print_sym_info.py SCRIPT_ARG= 6 | # 7 | # Example output for SCRIPT_ARG=MODULES: 8 | # 9 | # menuconfig MODULES 10 | # bool 11 | # prompt "Enable loadable module support" 12 | # option modules 13 | # help 14 | # Kernel modules are small pieces of compiled code which can 15 | # be inserted in the running kernel, rather than being 16 | # permanently built into the kernel. You use the "modprobe" 17 | # tool to add (and sometimes remove) them. If you say Y here, 18 | # many parts of the kernel can be built as modules (by 19 | # answering M instead of Y where indicated): this is most 20 | # useful for infrequently used options which are not required 21 | # for booting. For more information, see the man pages for 22 | # modprobe, lsmod, modinfo, insmod and rmmod. 23 | # 24 | # If you say Y here, you will need to run "make 25 | # modules_install" to put the modules under /lib/modules/ 26 | # where modprobe can find them (you may need to be root to do 27 | # this). 28 | # 29 | # If unsure, say Y. 30 | # 31 | # value = n 32 | # visibility = y 33 | # currently assignable values: n, y 34 | # defined at init/Kconfig:1674 35 | 36 | import sys 37 | 38 | from kconfiglib import Kconfig, TRI_TO_STR 39 | 40 | 41 | if len(sys.argv) < 3: 42 | sys.exit('Pass symbol name (without "CONFIG_" prefix) with SCRIPT_ARG=') 43 | 44 | kconf = Kconfig(sys.argv[1]) 45 | sym = kconf.syms[sys.argv[2]] 46 | 47 | print(sym) 48 | print("value = " + sym.str_value) 49 | print("visibility = " + TRI_TO_STR[sym.visibility]) 50 | print("currently assignable values: " + 51 | ", ".join([TRI_TO_STR[v] for v in sym.assignable])) 52 | 53 | for node in sym.nodes: 54 | print("defined at {}:{}".format(node.filename, node.linenr)) 55 | -------------------------------------------------------------------------------- /examples/print_tree.py: -------------------------------------------------------------------------------- 1 | # Prints the menu tree of the configuration. Dependencies between symbols can 2 | # sometimes implicitly alter the menu structure (see kconfig-language.txt), and 3 | # that's implemented too. 4 | # 5 | # Note: See the Kconfig.node_iter() function as well, which provides a simpler 6 | # interface for walking the menu tree. 7 | # 8 | # Usage: 9 | # 10 | # $ make [ARCH=] scriptconfig SCRIPT=Kconfiglib/examples/print_tree.py 11 | # 12 | # Example output: 13 | # 14 | # ... 15 | # config HAVE_KERNEL_LZO 16 | # config HAVE_KERNEL_LZ4 17 | # choice 18 | # config KERNEL_GZIP 19 | # config KERNEL_BZIP2 20 | # config KERNEL_LZMA 21 | # config KERNEL_XZ 22 | # config KERNEL_LZO 23 | # config KERNEL_LZ4 24 | # config DEFAULT_HOSTNAME 25 | # config SWAP 26 | # config SYSVIPC 27 | # config SYSVIPC_SYSCTL 28 | # config POSIX_MQUEUE 29 | # config POSIX_MQUEUE_SYSCTL 30 | # config CROSS_MEMORY_ATTACH 31 | # config FHANDLE 32 | # config USELIB 33 | # config AUDIT 34 | # config HAVE_ARCH_AUDITSYSCALL 35 | # config AUDITSYSCALL 36 | # config AUDIT_WATCH 37 | # config AUDIT_TREE 38 | # menu "IRQ subsystem" 39 | # config MAY_HAVE_SPARSE_IRQ 40 | # config GENERIC_IRQ_LEGACY 41 | # config GENERIC_IRQ_PROBE 42 | # ... 43 | 44 | import sys 45 | 46 | from kconfiglib import Kconfig, Symbol, Choice, MENU, COMMENT 47 | 48 | 49 | def indent_print(s, indent): 50 | print(indent*" " + s) 51 | 52 | 53 | def print_items(node, indent): 54 | while node: 55 | if isinstance(node.item, Symbol): 56 | indent_print("config " + node.item.name, indent) 57 | 58 | elif isinstance(node.item, Choice): 59 | indent_print("choice", indent) 60 | 61 | elif node.item == MENU: 62 | indent_print('menu "{}"'.format(node.prompt[0]), indent) 63 | 64 | elif node.item == COMMENT: 65 | indent_print('comment "{}"'.format(node.prompt[0]), indent) 66 | 67 | 68 | if node.list: 69 | print_items(node.list, indent + 2) 70 | 71 | node = node.next 72 | 73 | 74 | kconf = Kconfig(sys.argv[1]) 75 | print_items(kconf.top_node, 0) 76 | -------------------------------------------------------------------------------- /genconfig.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2018-2019, Ulf Magnusson 4 | # SPDX-License-Identifier: ISC 5 | 6 | """ 7 | Generates a header file with #defines from the configuration, matching the 8 | format of include/generated/autoconf.h in the Linux kernel. 9 | 10 | Optionally, also writes the configuration output as a .config file. See 11 | --config-out. 12 | 13 | The --sync-deps, --file-list, and --env-list options generate information that 14 | can be used to avoid needless rebuilds/reconfigurations. 15 | 16 | Before writing a header or configuration file, Kconfiglib compares the old 17 | contents of the file against the new contents. If there's no change, the write 18 | is skipped. This avoids updating file metadata like the modification time, and 19 | might save work depending on your build setup. 20 | 21 | By default, the configuration is generated from '.config'. A different 22 | configuration file can be passed in the KCONFIG_CONFIG environment variable. 23 | 24 | A custom header string can be inserted at the beginning of generated 25 | configuration and header files by setting the KCONFIG_CONFIG_HEADER and 26 | KCONFIG_AUTOHEADER_HEADER environment variables, respectively (this also works 27 | for other scripts). The string is not automatically made a comment (this is by 28 | design, to allow anything to be added), and no trailing newline is added, so 29 | add '/* */', '#', and newlines as appropriate. 30 | 31 | See https://www.gnu.org/software/make/manual/make.html#Multi_002dLine for a 32 | handy way to define multi-line variables in makefiles, for use with custom 33 | headers. Remember to export the variable to the environment. 34 | """ 35 | import argparse 36 | import os 37 | import sys 38 | 39 | import kconfiglib 40 | 41 | 42 | DEFAULT_SYNC_DEPS_PATH = "deps/" 43 | 44 | 45 | def main(): 46 | parser = argparse.ArgumentParser( 47 | formatter_class=argparse.RawDescriptionHelpFormatter, 48 | description=__doc__) 49 | 50 | parser.add_argument( 51 | "--header-path", 52 | metavar="HEADER_FILE", 53 | help=""" 54 | Path to write the generated header file to. If not specified, the path in the 55 | environment variable KCONFIG_AUTOHEADER is used if it is set, and 'config.h' 56 | otherwise. 57 | """) 58 | 59 | parser.add_argument( 60 | "--config-out", 61 | metavar="CONFIG_FILE", 62 | help=""" 63 | Write the configuration to CONFIG_FILE. This is useful if you include .config 64 | files in Makefiles, as the generated configuration file will be a full .config 65 | file even if .config is outdated. The generated configuration matches what 66 | olddefconfig would produce. If you use sync-deps, you can include 67 | deps/auto.conf instead. --config-out is meant for cases where incremental build 68 | information isn't needed. 69 | """) 70 | 71 | parser.add_argument( 72 | "--sync-deps", 73 | metavar="OUTPUT_DIR", 74 | nargs="?", 75 | const=DEFAULT_SYNC_DEPS_PATH, 76 | help=""" 77 | Enable generation of symbol dependency information for incremental builds, 78 | optionally specifying the output directory (default: {}). See the docstring of 79 | Kconfig.sync_deps() in Kconfiglib for more information. 80 | """.format(DEFAULT_SYNC_DEPS_PATH)) 81 | 82 | parser.add_argument( 83 | "--file-list", 84 | metavar="OUTPUT_FILE", 85 | help=""" 86 | Write a list of all Kconfig files to OUTPUT_FILE, with one file per line. The 87 | paths are relative to $srctree (or to the current directory if $srctree is 88 | unset). Files appear in the order they're 'source'd. 89 | """) 90 | 91 | parser.add_argument( 92 | "--env-list", 93 | metavar="OUTPUT_FILE", 94 | help=""" 95 | Write a list of all environment variables referenced in Kconfig files to 96 | OUTPUT_FILE, with one variable per line. Each line has the format NAME=VALUE. 97 | Only environment variables referenced with the preprocessor $(VAR) syntax are 98 | included, and not variables referenced with the older $VAR syntax (which is 99 | only supported for backwards compatibility). 100 | """) 101 | 102 | parser.add_argument( 103 | "kconfig", 104 | metavar="KCONFIG", 105 | nargs="?", 106 | default="Kconfig", 107 | help="Top-level Kconfig file (default: Kconfig)") 108 | 109 | args = parser.parse_args() 110 | 111 | 112 | kconf = kconfiglib.Kconfig(args.kconfig, suppress_traceback=True) 113 | kconf.load_config() 114 | 115 | if args.header_path is None: 116 | if "KCONFIG_AUTOHEADER" in os.environ: 117 | kconf.write_autoconf() 118 | else: 119 | # Kconfiglib defaults to include/generated/autoconf.h to be 120 | # compatible with the C tools. 'config.h' is used here instead for 121 | # backwards compatibility. It's probably a saner default for tools 122 | # as well. 123 | kconf.write_autoconf("config.h") 124 | else: 125 | kconf.write_autoconf(args.header_path) 126 | 127 | if args.config_out is not None: 128 | kconf.write_config(args.config_out, save_old=False) 129 | 130 | if args.sync_deps is not None: 131 | kconf.sync_deps(args.sync_deps) 132 | 133 | if args.file_list is not None: 134 | with _open_write(args.file_list) as f: 135 | for path in kconf.kconfig_filenames: 136 | f.write(path + "\n") 137 | 138 | if args.env_list is not None: 139 | with _open_write(args.env_list) as f: 140 | for env_var in kconf.env_vars: 141 | f.write("{}={}\n".format(env_var, os.environ[env_var])) 142 | 143 | 144 | def _open_write(path): 145 | # Python 2/3 compatibility. io.open() is available on both, but makes 146 | # write() expect 'unicode' strings on Python 2. 147 | 148 | if sys.version_info[0] < 3: 149 | return open(path, "w") 150 | return open(path, "w", encoding="utf-8") 151 | 152 | 153 | if __name__ == "__main__": 154 | main() 155 | -------------------------------------------------------------------------------- /listnewconfig.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2018-2019, Ulf Magnusson 4 | # SPDX-License-Identifier: ISC 5 | 6 | """ 7 | Lists all user-modifiable symbols that are not given a value in the 8 | configuration file. Usually, these are new symbols that have been added to the 9 | Kconfig files. 10 | 11 | The default configuration filename is '.config'. A different filename can be 12 | passed in the KCONFIG_CONFIG environment variable. 13 | """ 14 | from __future__ import print_function 15 | 16 | import argparse 17 | import sys 18 | 19 | from kconfiglib import Kconfig, BOOL, TRISTATE, INT, HEX, STRING, TRI_TO_STR 20 | 21 | 22 | def main(): 23 | parser = argparse.ArgumentParser( 24 | formatter_class=argparse.RawDescriptionHelpFormatter, 25 | description=__doc__) 26 | 27 | parser.add_argument( 28 | "--show-help", "-l", 29 | action="store_true", 30 | help="Show any help texts as well") 31 | 32 | parser.add_argument( 33 | "kconfig", 34 | metavar="KCONFIG", 35 | nargs="?", 36 | default="Kconfig", 37 | help="Top-level Kconfig file (default: Kconfig)") 38 | 39 | args = parser.parse_args() 40 | 41 | kconf = Kconfig(args.kconfig, suppress_traceback=True) 42 | # Make it possible to filter this message out 43 | print(kconf.load_config(), file=sys.stderr) 44 | 45 | for sym in kconf.unique_defined_syms: 46 | # Only show symbols that can be toggled. Choice symbols are a special 47 | # case in that sym.assignable will be (2,) (length 1) for visible 48 | # symbols in choices in y mode, but they can still be toggled by 49 | # selecting some other symbol. 50 | if sym.user_value is None and \ 51 | (len(sym.assignable) > 1 or 52 | (sym.visibility and (sym.orig_type in (INT, HEX, STRING) or 53 | sym.choice))): 54 | 55 | # Don't reuse the 'config_string' format for bool/tristate symbols, 56 | # to show n-valued symbols as 'CONFIG_FOO=n' instead of 57 | # '# CONFIG_FOO is not set'. This matches the C tools. 58 | if sym.orig_type in (BOOL, TRISTATE): 59 | s = "{}{}={}\n".format(kconf.config_prefix, sym.name, 60 | TRI_TO_STR[sym.tri_value]) 61 | else: 62 | s = sym.config_string 63 | 64 | print(s, end="") 65 | if args.show_help: 66 | for node in sym.nodes: 67 | if node.help is not None: 68 | # Indent by two spaces. textwrap.indent() is not 69 | # available in Python 2 (it's 3.3+). 70 | print("\n".join(" " + line 71 | for line in node.help.split("\n"))) 72 | break 73 | 74 | 75 | if __name__ == "__main__": 76 | main() 77 | -------------------------------------------------------------------------------- /makefile.patch: -------------------------------------------------------------------------------- 1 | From 93daf46f309b0c8f86149ef58c4906387d054c22 Mon Sep 17 00:00:00 2001 2 | From: Ulf Magnusson 3 | Date: Tue, 9 Jun 2015 13:01:34 +0200 4 | Subject: [PATCH] Kconfiglib scripts/kconfig/Makefile patch 5 | 6 | --- 7 | scripts/kconfig/Makefile | 29 +++++++++++++++++++++++++++++ 8 | 1 file changed, 29 insertions(+) 9 | 10 | diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile 11 | index 3f327e21f60e..8b7dd1292005 100644 12 | --- a/scripts/kconfig/Makefile 13 | +++ b/scripts/kconfig/Makefile 14 | @@ -27,2 +27,31 @@ gconfig: $(obj)/gconf 15 | 16 | +PHONY += scriptconfig iscriptconfig kmenuconfig guiconfig dumpvarsconfig 17 | + 18 | +PYTHONCMD ?= python 19 | +kpython := PYTHONPATH=$(srctree)/Kconfiglib:$$PYTHONPATH $(PYTHONCMD) 20 | + 21 | +ifneq ($(filter scriptconfig,$(MAKECMDGOALS)),) 22 | +ifndef SCRIPT 23 | +$(error Use "make scriptconfig SCRIPT= [SCRIPT_ARG=]") 24 | +endif 25 | +endif 26 | + 27 | +scriptconfig: 28 | + $(Q)$(kpython) $(SCRIPT) $(Kconfig) $(if $(SCRIPT_ARG),"$(SCRIPT_ARG)") 29 | + 30 | +iscriptconfig: 31 | + $(Q)$(kpython) -i -c \ 32 | + "import kconfiglib; \ 33 | + kconf = kconfiglib.Kconfig('$(Kconfig)'); \ 34 | + print('A Kconfig instance \'kconf\' for the architecture $(ARCH) has been created.')" 35 | + 36 | +kmenuconfig: 37 | + $(Q)$(kpython) $(srctree)/Kconfiglib/menuconfig.py $(Kconfig) 38 | + 39 | +guiconfig: 40 | + $(Q)$(kpython) $(srctree)/Kconfiglib/guiconfig.py $(Kconfig) 41 | + 42 | +dumpvarsconfig: 43 | + $(Q)$(kpython) $(srctree)/Kconfiglib/examples/dumpvars.py $(Kconfig) 44 | + 45 | menuconfig: $(obj)/mconf 46 | -- 47 | 2.20.1 48 | 49 | -------------------------------------------------------------------------------- /oldconfig.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2018-2019, Ulf Magnusson 4 | # SPDX-License-Identifier: ISC 5 | 6 | """ 7 | Implements oldconfig functionality. 8 | 9 | 1. Loads existing .config 10 | 2. Prompts for the value of all modifiable symbols/choices that 11 | aren't already set in the .config 12 | 3. Writes an updated .config 13 | 14 | The default input/output filename is '.config'. A different filename can be 15 | passed in the KCONFIG_CONFIG environment variable. 16 | 17 | When overwriting a configuration file, the old version is saved to 18 | .old (e.g. .config.old). 19 | 20 | Entering '?' displays the help text of the symbol/choice, if any. 21 | 22 | Unlike 'make oldconfig', this script doesn't print menu titles and comments, 23 | but gives Kconfig definition locations. Printing menus and comments would be 24 | pretty easy to add: Look at the parents of each item, and print all menu 25 | prompts and comments unless they have already been printed (assuming you want 26 | to skip "irrelevant" menus). 27 | """ 28 | from __future__ import print_function 29 | 30 | import sys 31 | 32 | from kconfiglib import Symbol, Choice, BOOL, TRISTATE, HEX, standard_kconfig 33 | 34 | 35 | # Python 2/3 compatibility hack 36 | if sys.version_info[0] < 3: 37 | input = raw_input 38 | 39 | 40 | def _main(): 41 | # Earlier symbols in Kconfig files might depend on later symbols and become 42 | # visible if their values change. This flag is set to True if the value of 43 | # any symbol changes, in which case we rerun the oldconfig to check for new 44 | # visible symbols. 45 | global conf_changed 46 | 47 | kconf = standard_kconfig(__doc__) 48 | print(kconf.load_config()) 49 | 50 | while True: 51 | conf_changed = False 52 | 53 | for node in kconf.node_iter(): 54 | oldconfig(node) 55 | 56 | if not conf_changed: 57 | break 58 | 59 | print(kconf.write_config()) 60 | 61 | 62 | def oldconfig(node): 63 | """ 64 | Prompts the user for a value if node.item is a visible symbol/choice with 65 | no user value. 66 | """ 67 | # See main() 68 | global conf_changed 69 | 70 | # Only symbols and choices can be configured 71 | if not isinstance(node.item, (Symbol, Choice)): 72 | return 73 | 74 | # Skip symbols and choices that aren't visible 75 | if not node.item.visibility: 76 | return 77 | 78 | # Skip symbols and choices that don't have a prompt (at this location) 79 | if not node.prompt: 80 | return 81 | 82 | if isinstance(node.item, Symbol): 83 | sym = node.item 84 | 85 | # Skip symbols that already have a user value 86 | if sym.user_value is not None: 87 | return 88 | 89 | # Skip symbols that can only have a single value, due to selects 90 | if len(sym.assignable) == 1: 91 | return 92 | 93 | # Skip symbols in choices in y mode. We ask once for the entire choice 94 | # instead. 95 | if sym.choice and sym.choice.tri_value == 2: 96 | return 97 | 98 | # Loop until the user enters a valid value or enters a blank string 99 | # (for the default value) 100 | while True: 101 | val = input("{} ({}) [{}] ".format( 102 | node.prompt[0], _name_and_loc_str(sym), 103 | _default_value_str(sym))) 104 | 105 | if val == "?": 106 | _print_help(node) 107 | continue 108 | 109 | # Substitute a blank string with the default value the symbol 110 | # would get 111 | if not val: 112 | val = sym.str_value 113 | 114 | # Automatically add a "0x" prefix for hex symbols, like the 115 | # menuconfig interface does. This isn't done when loading .config 116 | # files, hence why set_value() doesn't do it automatically. 117 | if sym.type == HEX and not val.startswith(("0x", "0X")): 118 | val = "0x" + val 119 | 120 | old_str_val = sym.str_value 121 | 122 | # Kconfiglib itself will print a warning here if the value 123 | # is invalid, so we don't need to bother 124 | if sym.set_value(val): 125 | # Valid value input. We're done with this node. 126 | 127 | if sym.str_value != old_str_val: 128 | conf_changed = True 129 | 130 | return 131 | 132 | else: 133 | choice = node.item 134 | 135 | # Skip choices that already have a visible user selection... 136 | if choice.user_selection and choice.user_selection.visibility == 2: 137 | # ...unless there are new visible symbols in the choice. (We know 138 | # they have y (2) visibility in that case, because m-visible 139 | # symbols get demoted to n-visibility in y-mode choices, and the 140 | # user-selected symbol had visibility y.) 141 | for sym in choice.syms: 142 | if sym is not choice.user_selection and sym.visibility and \ 143 | sym.user_value is None: 144 | # New visible symbols in the choice 145 | break 146 | else: 147 | # No new visible symbols in the choice 148 | return 149 | 150 | # Get a list of available selections. The mode of the choice limits 151 | # the visibility of the choice value symbols, so this will indirectly 152 | # skip choices in n and m mode. 153 | options = [sym for sym in choice.syms if sym.visibility == 2] 154 | 155 | if not options: 156 | # No y-visible choice value symbols 157 | return 158 | 159 | # Loop until the user enters a valid selection or a blank string (for 160 | # the default selection) 161 | while True: 162 | print("{} ({})".format(node.prompt[0], _name_and_loc_str(choice))) 163 | 164 | for i, sym in enumerate(options, 1): 165 | print("{} {}. {} ({})".format( 166 | ">" if sym is choice.selection else " ", 167 | i, 168 | # Assume people don't define choice symbols with multiple 169 | # prompts. That generates a warning anyway. 170 | sym.nodes[0].prompt[0], 171 | sym.name)) 172 | 173 | sel_index = input("choice[1-{}]: ".format(len(options))) 174 | 175 | if sel_index == "?": 176 | _print_help(node) 177 | continue 178 | 179 | # Pick the default selection if the string is blank 180 | if not sel_index: 181 | choice.selection.set_value(2) 182 | break 183 | 184 | try: 185 | sel_index = int(sel_index) 186 | except ValueError: 187 | print("Bad index", file=sys.stderr) 188 | continue 189 | 190 | if not 1 <= sel_index <= len(options): 191 | print("Bad index", file=sys.stderr) 192 | continue 193 | 194 | # Valid selection 195 | 196 | if options[sel_index - 1].tri_value != 2: 197 | conf_changed = True 198 | 199 | options[sel_index - 1].set_value(2) 200 | break 201 | 202 | # Give all of the non-selected visible choice symbols the user value n. 203 | # This makes it so that the choice is no longer considered new once we 204 | # do additional passes, if the reason that it was considered new was 205 | # that it had new visible choice symbols. 206 | # 207 | # Only giving visible choice symbols the user value n means we will 208 | # prompt for the choice again if later user selections make more new 209 | # choice symbols visible, which is correct. 210 | for sym in choice.syms: 211 | if sym is not choice.user_selection and sym.visibility: 212 | sym.set_value(0) 213 | 214 | 215 | def _name_and_loc_str(sc): 216 | # Helper for printing the name of the symbol/choice 'sc' along with the 217 | # location(s) in the Kconfig files where it is defined. Unnamed choices 218 | # return "choice" instead of the name. 219 | 220 | return "{}, defined at {}".format( 221 | sc.name or "choice", 222 | ", ".join("{}:{}".format(node.filename, node.linenr) 223 | for node in sc.nodes)) 224 | 225 | 226 | def _print_help(node): 227 | print("\n" + (node.help or "No help text\n")) 228 | 229 | 230 | def _default_value_str(sym): 231 | # Returns the "m/M/y" string in e.g. 232 | # 233 | # TRISTATE_SYM prompt (TRISTATE_SYM, defined at Kconfig:9) [n/M/y]: 234 | # 235 | # For string/int/hex, returns the default value as-is. 236 | 237 | if sym.type in (BOOL, TRISTATE): 238 | return "/".join(("NMY" if sym.tri_value == tri else "nmy")[tri] 239 | for tri in sym.assignable) 240 | 241 | # string/int/hex 242 | return sym.str_value 243 | 244 | 245 | if __name__ == "__main__": 246 | _main() 247 | -------------------------------------------------------------------------------- /olddefconfig.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2018-2019, Ulf Magnusson 4 | # SPDX-License-Identifier: ISC 5 | 6 | """ 7 | Updates an old .config file or creates a new one, by filling in default values 8 | for all new symbols. This is the same as picking the default selection for all 9 | symbols in oldconfig, or entering the menuconfig interface and immediately 10 | saving. 11 | 12 | The default input/output filename is '.config'. A different filename can be 13 | passed in the KCONFIG_CONFIG environment variable. 14 | 15 | When overwriting a configuration file, the old version is saved to 16 | .old (e.g. .config.old). 17 | """ 18 | import kconfiglib 19 | 20 | 21 | def main(): 22 | kconf = kconfiglib.standard_kconfig(__doc__) 23 | print(kconf.load_config()) 24 | print(kconf.write_config()) 25 | 26 | 27 | if __name__ == "__main__": 28 | main() 29 | -------------------------------------------------------------------------------- /savedefconfig.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2019, Ulf Magnusson 4 | # SPDX-License-Identifier: ISC 5 | 6 | """ 7 | Saves a minimal configuration file that only lists symbols that differ in value 8 | from their defaults. Loading such a configuration file is equivalent to loading 9 | the "full" configuration file. 10 | 11 | Minimal configuration files are handy to start from when editing configuration 12 | files by hand. 13 | 14 | The default input configuration file is '.config'. A different input filename 15 | can be passed in the KCONFIG_CONFIG environment variable. 16 | 17 | Note: Minimal configurations can also be generated from within the menuconfig 18 | interface. 19 | """ 20 | import argparse 21 | 22 | import kconfiglib 23 | 24 | 25 | def main(): 26 | parser = argparse.ArgumentParser( 27 | formatter_class=argparse.RawDescriptionHelpFormatter, 28 | description=__doc__) 29 | 30 | parser.add_argument( 31 | "--kconfig", 32 | default="Kconfig", 33 | help="Top-level Kconfig file (default: Kconfig)") 34 | 35 | parser.add_argument( 36 | "--out", 37 | metavar="MINIMAL_CONFIGURATION", 38 | default="defconfig", 39 | help="Output filename for minimal configuration (default: defconfig)") 40 | 41 | args = parser.parse_args() 42 | 43 | kconf = kconfiglib.Kconfig(args.kconfig, suppress_traceback=True) 44 | print(kconf.load_config()) 45 | print(kconf.write_min_config(args.out)) 46 | 47 | 48 | if __name__ == "__main__": 49 | main() 50 | -------------------------------------------------------------------------------- /setconfig.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2019, Ulf Magnusson 4 | # SPDX-License-Identifier: ISC 5 | 6 | """ 7 | Simple utility for setting configuration values from the command line. 8 | 9 | Sample usage: 10 | 11 | $ setconfig FOO_SUPPORT=y BAR_BITS=8 12 | 13 | Note: Symbol names should not be prefixed with 'CONFIG_'. 14 | 15 | The exit status on errors is 1. 16 | 17 | The default input/output configuration file is '.config'. A different filename 18 | can be passed in the KCONFIG_CONFIG environment variable. 19 | 20 | When overwriting a configuration file, the old version is saved to 21 | .old (e.g. .config.old). 22 | """ 23 | import argparse 24 | import sys 25 | 26 | import kconfiglib 27 | 28 | 29 | def main(): 30 | parser = argparse.ArgumentParser( 31 | formatter_class=argparse.RawDescriptionHelpFormatter, 32 | description=__doc__) 33 | 34 | parser.add_argument( 35 | "--kconfig", 36 | default="Kconfig", 37 | help="Top-level Kconfig file (default: Kconfig)") 38 | 39 | parser.add_argument( 40 | "--no-check-exists", 41 | dest="check_exists", 42 | action="store_false", 43 | help="Ignore assignments to non-existent symbols instead of erroring " 44 | "out") 45 | 46 | parser.add_argument( 47 | "--no-check-value", 48 | dest="check_value", 49 | action="store_false", 50 | help="Ignore assignments that didn't \"take\" (where the symbol got a " 51 | "different value, e.g. due to unsatisfied dependencies) instead " 52 | "of erroring out") 53 | 54 | parser.add_argument( 55 | "assignments", 56 | metavar="ASSIGNMENT", 57 | nargs="*", 58 | help="A 'NAME=value' assignment") 59 | 60 | args = parser.parse_args() 61 | 62 | kconf = kconfiglib.Kconfig(args.kconfig, suppress_traceback=True) 63 | print(kconf.load_config()) 64 | 65 | for arg in args.assignments: 66 | if "=" not in arg: 67 | sys.exit("error: no '=' in assignment: '{}'".format(arg)) 68 | name, value = arg.split("=", 1) 69 | 70 | if name not in kconf.syms: 71 | if not args.check_exists: 72 | continue 73 | sys.exit("error: no symbol '{}' in configuration".format(name)) 74 | 75 | sym = kconf.syms[name] 76 | 77 | if not sym.set_value(value): 78 | sys.exit("error: '{}' is an invalid value for the {} symbol {}" 79 | .format(value, kconfiglib.TYPE_TO_STR[sym.orig_type], 80 | name)) 81 | 82 | if args.check_value and sym.str_value != value: 83 | sys.exit("error: {} was assigned the value '{}', but got the " 84 | "value '{}'. Check the symbol's dependencies, and make " 85 | "sure that it has a prompt." 86 | .format(name, value, sym.str_value)) 87 | 88 | print(kconf.write_config()) 89 | 90 | 91 | if __name__ == "__main__": 92 | main() 93 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [bdist_wheel] 2 | # We support both Python 2 and Python 3 3 | universal = 1 4 | 5 | [metadata] 6 | # Include the license file in wheels 7 | license_file = LICENSE.txt 8 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import io 2 | import os 3 | 4 | import setuptools 5 | 6 | 7 | setuptools.setup( 8 | name="kconfiglib", 9 | # MAJOR.MINOR.PATCH, per http://semver.org 10 | version="14.1.0", 11 | description="A flexible Python Kconfig implementation", 12 | 13 | # Make sure that README.rst decodes on Python 3 in environments that use 14 | # the C locale (which implies ASCII), by explicitly giving the encoding. 15 | # 16 | # io.open() has the 'encoding' parameter on both Python 2 and 3. open() 17 | # doesn't have it on Python 2. This lets us use the same code for both. 18 | long_description=io.open( 19 | os.path.join(os.path.dirname(__file__), "README.rst"), 20 | encoding="utf-8" 21 | ).read(), 22 | 23 | url="https://github.com/ulfalizer/Kconfiglib", 24 | author='Ulf "Ulfalizer" Magnusson', 25 | author_email="ulfalizer@gmail.com", 26 | keywords="kconfig, kbuild, menuconfig, configuration-management", 27 | license="ISC", 28 | 29 | py_modules=( 30 | "kconfiglib", 31 | "menuconfig", 32 | "guiconfig", 33 | "genconfig", 34 | "oldconfig", 35 | "olddefconfig", 36 | "savedefconfig", 37 | "defconfig", 38 | "alldefconfig", 39 | "allnoconfig", 40 | "allmodconfig", 41 | "allyesconfig", 42 | "listnewconfig", 43 | "setconfig", 44 | ), 45 | 46 | entry_points={ 47 | "console_scripts": ( 48 | "menuconfig = menuconfig:_main", 49 | "guiconfig = guiconfig:_main", 50 | "genconfig = genconfig:main", 51 | "oldconfig = oldconfig:_main", 52 | "olddefconfig = olddefconfig:main", 53 | "savedefconfig = savedefconfig:main", 54 | "defconfig = defconfig:main", 55 | "alldefconfig = alldefconfig:main", 56 | "allnoconfig = allnoconfig:main", 57 | "allmodconfig = allmodconfig:main", 58 | "allyesconfig = allyesconfig:main", 59 | "listnewconfig = listnewconfig:main", 60 | "setconfig = setconfig:main", 61 | ) 62 | }, 63 | 64 | # Note: windows-curses is not automatically installed on Windows anymore, 65 | # because it made Kconfiglib impossible to install on MSYS2 with pip 66 | 67 | # Needs support for unnumbered {} in format() and argparse 68 | python_requires=">=2.7,!=3.0.*,!=3.1.*", 69 | 70 | project_urls={ 71 | "GitHub repository": "https://github.com/ulfalizer/Kconfiglib", 72 | "Examples": "https://github.com/ulfalizer/Kconfiglib/tree/master/examples", 73 | }, 74 | 75 | classifiers=[ 76 | "Development Status :: 5 - Production/Stable", 77 | "Intended Audience :: Developers", 78 | "Topic :: Software Development :: Build Tools", 79 | "Topic :: System :: Operating System Kernels :: Linux", 80 | "License :: OSI Approved :: ISC License (ISCL)", 81 | "Operating System :: POSIX", 82 | "Operating System :: Microsoft :: Windows", 83 | "Programming Language :: Python :: 2", 84 | "Programming Language :: Python :: 2.7", 85 | "Programming Language :: Python :: 3", 86 | "Programming Language :: Python :: 3.2", 87 | "Programming Language :: Python :: 3.3", 88 | "Programming Language :: Python :: 3.4", 89 | "Programming Language :: Python :: 3.5", 90 | "Programming Language :: Python :: 3.6", 91 | "Programming Language :: Python :: 3.7", 92 | "Programming Language :: Python :: 3.8", 93 | "Programming Language :: Python :: Implementation :: CPython", 94 | "Programming Language :: Python :: Implementation :: PyPy", 95 | ] 96 | ) 97 | -------------------------------------------------------------------------------- /tests/Kappend: -------------------------------------------------------------------------------- 1 | config MODULES 2 | def_bool y 3 | 4 | config BOOL 5 | bool "bool 1" 6 | 7 | config STRING 8 | string "string" 9 | 10 | config IGNOREME 11 | bool "ignore me" 12 | default y 13 | -------------------------------------------------------------------------------- /tests/Kassignable: -------------------------------------------------------------------------------- 1 | config MODULES 2 | bool "modules" 3 | option modules 4 | 5 | 6 | # Things that should never be .assignable 7 | 8 | if UNDEFINED && "const" 9 | endif 10 | 11 | config NO_PROMPT 12 | bool 13 | 14 | config STRING 15 | string "string" 16 | 17 | config INT 18 | int "int" 19 | 20 | config HEX 21 | hex "hex" 22 | 23 | 24 | # Non-selected symbols 25 | 26 | config Y_VIS_BOOL 27 | bool "y-vis bool" 28 | 29 | config M_VIS_BOOL 30 | bool "m-vis bool" if m 31 | 32 | config N_VIS_BOOL 33 | bool "n-vis bool" if n 34 | 35 | config Y_VIS_TRI 36 | tristate "y-vis tri" 37 | 38 | config M_VIS_TRI 39 | tristate "m-vis tri" if m 40 | 41 | config N_VIS_TRI 42 | tristate "n-vis tri" if n 43 | 44 | 45 | # Symbols selected to y 46 | 47 | config Y_SELECTOR 48 | def_tristate y 49 | 50 | select Y_SEL_Y_VIS_BOOL 51 | select Y_SEL_M_VIS_BOOL 52 | select Y_SEL_N_VIS_BOOL 53 | 54 | select Y_SEL_Y_VIS_TRI 55 | select Y_SEL_M_VIS_TRI 56 | select Y_SEL_N_VIS_TRI 57 | 58 | config Y_SEL_Y_VIS_BOOL 59 | bool "y-sel y-vis bool" 60 | 61 | config Y_SEL_M_VIS_BOOL 62 | bool "y-sel m-vis bool" if m 63 | 64 | config Y_SEL_N_VIS_BOOL 65 | bool "y-sel n-vis bool" if n 66 | 67 | config Y_SEL_Y_VIS_TRI 68 | tristate "y-sel y-vis tri" 69 | 70 | config Y_SEL_M_VIS_TRI 71 | tristate "y-sel m-vis tri" if m 72 | 73 | config Y_SEL_N_VIS_TRI 74 | tristate "y-sel n-vis tri" if n 75 | 76 | 77 | # Symbols selected to m 78 | 79 | config M_SELECTOR 80 | def_tristate m 81 | 82 | select M_SEL_Y_VIS_BOOL 83 | select M_SEL_M_VIS_BOOL 84 | select M_SEL_N_VIS_BOOL 85 | 86 | select M_SEL_Y_VIS_TRI 87 | select M_SEL_M_VIS_TRI 88 | select M_SEL_N_VIS_TRI 89 | 90 | config M_SEL_Y_VIS_BOOL 91 | bool "m-sel y-vis bool" 92 | 93 | config M_SEL_M_VIS_BOOL 94 | bool "m-sel m-vis bool" if m 95 | 96 | config M_SEL_N_VIS_BOOL 97 | bool "m-sel n-vis bool" if n 98 | 99 | config M_SEL_Y_VIS_TRI 100 | tristate "m-sel y-vis tri" 101 | 102 | config M_SEL_M_VIS_TRI 103 | tristate "m-sel m-vis tri" if m 104 | 105 | config M_SEL_N_VIS_TRI 106 | tristate "m-sel n-vis tri" if n 107 | 108 | 109 | # Symbols implied to y 110 | 111 | config Y_IMPLIER 112 | def_tristate y 113 | 114 | imply Y_IMP_Y_VIS_BOOL 115 | imply Y_IMP_M_VIS_BOOL 116 | imply Y_IMP_N_VIS_BOOL 117 | 118 | imply Y_IMP_Y_VIS_TRI 119 | imply Y_IMP_M_VIS_TRI 120 | imply Y_IMP_N_VIS_TRI 121 | 122 | config Y_IMP_Y_VIS_BOOL 123 | bool "y-imp y-vis bool" 124 | 125 | config Y_IMP_M_VIS_BOOL 126 | bool "y-imp m-vis bool" if m 127 | 128 | config Y_IMP_N_VIS_BOOL 129 | bool "y-imp n-vis bool" if n 130 | 131 | config Y_IMP_Y_VIS_TRI 132 | tristate "y-imp y-vis tri" 133 | 134 | config Y_IMP_M_VIS_TRI 135 | tristate "y-imp m-vis tri" if m 136 | 137 | config Y_IMP_N_VIS_TRI 138 | tristate "y-imp n-vis tri" if n 139 | 140 | 141 | # Symbols implied to m (never affects assignable values) 142 | 143 | config M_IMPLIER 144 | def_tristate m 145 | 146 | imply M_IMP_Y_VIS_BOOL 147 | imply M_IMP_M_VIS_BOOL 148 | imply M_IMP_N_VIS_BOOL 149 | 150 | imply M_IMP_Y_VIS_TRI 151 | imply M_IMP_M_VIS_TRI 152 | imply M_IMP_N_VIS_TRI 153 | 154 | config M_IMP_Y_VIS_BOOL 155 | bool "m-imp y-vis bool" 156 | 157 | config M_IMP_M_VIS_BOOL 158 | bool "m-imp m-vis bool" if m 159 | 160 | config M_IMP_N_VIS_BOOL 161 | bool "m-imp n-vis bool" if n 162 | 163 | config M_IMP_Y_VIS_TRI 164 | tristate "m-imp y-vis tri" 165 | 166 | config M_IMP_M_VIS_TRI 167 | tristate "m-imp m-vis tri" if m 168 | 169 | config M_IMP_N_VIS_TRI 170 | tristate "m-imp n-vis tri" if n 171 | 172 | 173 | # Symbols in y-mode choice 174 | 175 | choice Y_CHOICE 176 | bool "y-mode choice" 177 | 178 | config Y_CHOICE_BOOL 179 | bool "y-mode choice bool" 180 | 181 | config Y_CHOICE_TRISTATE 182 | tristate "y-mode choice tristate" 183 | 184 | config Y_CHOICE_N_VIS_TRISTATE 185 | tristate "y-mode choice tristate invisible" if n 186 | 187 | endchoice 188 | 189 | 190 | # Symbols in m/y-mode choice 191 | 192 | choice MY_CHOICE 193 | tristate "m/y-mode choice" 194 | 195 | config MY_CHOICE_BOOL 196 | bool "m/y-mode choice bool" 197 | 198 | config MY_CHOICE_TRISTATE 199 | tristate "m/y-mode choice tristate" 200 | 201 | config MY_CHOICE_N_VIS_TRISTATE 202 | tristate "m/y-mode choice tristate invisible" if n 203 | 204 | endchoice 205 | 206 | 207 | # Choices with some other possible modes 208 | 209 | choice NMY_CHOICE 210 | tristate "n/m/y-mode choice" 211 | optional 212 | endchoice 213 | 214 | choice NY_CHOICE 215 | bool "n/y-mode choice" 216 | optional 217 | endchoice 218 | 219 | choice NM_CHOICE 220 | tristate "n/m-mode choice" if m 221 | optional 222 | endchoice 223 | 224 | choice M_CHOICE 225 | tristate "m-mode choice" if m 226 | endchoice 227 | 228 | choice N_CHOICE 229 | tristate "n-mode choice" if n 230 | endchoice 231 | -------------------------------------------------------------------------------- /tests/Kchoice: -------------------------------------------------------------------------------- 1 | config MODULES 2 | bool "modules" 3 | 4 | # bool/tristate and optional 5 | 6 | choice BOOL 7 | bool "bool" 8 | config B_1 9 | tristate "B_1" 10 | config B_2 11 | tristate "B_2" 12 | endchoice 13 | 14 | choice BOOL_OPT 15 | bool "bool optional" 16 | optional 17 | config BO_1 18 | tristate "BO_1" 19 | config BO_2 20 | tristate "BO_2" 21 | endchoice 22 | 23 | choice TRISTATE 24 | tristate "tristate" 25 | config T_1 26 | tristate "T_1" 27 | config T_2 28 | tristate "T_2" 29 | endchoice 30 | 31 | choice TRISTATE_OPT 32 | tristate "tristate optional" 33 | optional 34 | config TO_1 35 | tristate "TO_1" 36 | config TO_2 37 | tristate "TO_2" 38 | endchoice 39 | 40 | # m-visibility 41 | 42 | choice BOOL_M 43 | bool "bool m" if m 44 | config BM_1 45 | tristate "BM_1" 46 | config BM_2 47 | tristate "BM_2" 48 | endchoice 49 | 50 | choice TRISTATE_M 51 | tristate "tristate m" if m 52 | config TM_1 53 | tristate "TM_1" 54 | config TM_2 55 | tristate "TM_2" 56 | endchoice 57 | 58 | # Defaults 59 | 60 | config TRISTATE_SYM 61 | tristate "tristate" 62 | 63 | choice DEFAULTS 64 | bool "defaults" 65 | default OPT_1 if n 66 | default OPT_2 if TRISTATE_SYM 67 | default OPT_4 68 | config OPT_1 69 | tristate "OPT_1" 70 | config OPT_2 71 | tristate "OPT_2" 72 | config OPT_3 73 | tristate "OPT_3" 74 | config OPT_4 75 | tristate "OPT_4" 76 | endchoice 77 | 78 | choice DEFAULTS_NOT_VISIBLE 79 | bool "defaults not visible" 80 | # Skipped due to condition 81 | default OPT_6 if n 82 | # Skipped because OPT_7 is not visible 83 | default OPT_7 84 | # This one should apply 85 | default OPT_8 86 | config OPT_5 87 | tristate "OPT_5" 88 | config OPT_6 89 | tristate "OPT_6" 90 | config OPT_7 91 | tristate "OPT_7" if n 92 | config OPT_8 93 | tristate "OPT_8" 94 | config OPT_9 95 | tristate "OPT_9" 96 | endchoice 97 | 98 | # Choices without an explicitly specified type should get the type of the first 99 | # symbol with a type 100 | 101 | choice NO_TYPE_BOOL 102 | prompt "no type bool" 103 | config NTB_1 104 | bool "NTB_1" 105 | config NTB_2 106 | tristate "NTB_2" 107 | endchoice 108 | 109 | choice NO_TYPE_TRISTATE 110 | prompt "no type tristate" 111 | config NTT_1 112 | config NTT_2 113 | tristate "NTB_2" 114 | config NTT_3 115 | bool "NTT_3" 116 | endchoice 117 | 118 | # Choice items without an explicitly specified type should get the type of the 119 | # choice 120 | 121 | choice MISSING_MEMBER_TYPES_1 122 | bool "missing member types" 123 | config MMT_1 124 | config MMT_2 125 | config MMT_3 126 | tristate 127 | endchoice 128 | 129 | choice MISSING_MEMBER_TYPES_2 130 | config MMT_4 131 | config MMT_5 132 | bool 133 | endchoice 134 | 135 | # Choice where the default selection (the first symbol) depends on another 136 | # symbol. If that symbol becomes 'n', the default selection should change to 137 | # the first visible symbol in the choice. 138 | 139 | choice DEFAULT_WITH_DEP 140 | bool "default with dep" 141 | 142 | config A 143 | bool "A" 144 | depends on DEP 145 | 146 | config B 147 | bool "B" 148 | 149 | endchoice 150 | 151 | config DEP 152 | bool "dep" 153 | 154 | # Choice with symbols that shouldn't be considered choice symbols because they 155 | # depend on the preceding symbol. This might be a kconfig bug, but some things 156 | # use it, so we need to emulate it. 157 | 158 | choice WEIRD_SYMS 159 | bool "weird symbols that aren't considered part of the choice" 160 | 161 | # Only WS1 is part of the choice 162 | config WS1 163 | bool "WS1" 164 | 165 | config WS2 166 | bool "WS2" 167 | depends on WS1 168 | 169 | config WS3 170 | bool 171 | depends on WS2 172 | 173 | config WS4 174 | bool 175 | depends on WS1 176 | 177 | config WS5 178 | bool "WS5" if WS1 179 | 180 | # 'if' has the same effect, so only WS6 is part of the choice 181 | config WS6 182 | bool "WS6" 183 | 184 | if WS6 185 | 186 | config WS7 187 | bool 188 | 189 | config WS8 190 | bool "WS8" 191 | 192 | endif 193 | 194 | # Should also be part of the choice 195 | config WS9 196 | bool "WS9" 197 | 198 | endchoice 199 | -------------------------------------------------------------------------------- /tests/Kdefconfig_existent: -------------------------------------------------------------------------------- 1 | # $FOO is "defconfig_2" 2 | 3 | config A 4 | string 5 | option defconfig_list 6 | default "Kconfiglib/tests/defconfig_1" if y && !n && n 7 | default "Kconfiglib/tests/$FOO" 8 | default "Kconfiglib/tests/defconfig_1" 9 | -------------------------------------------------------------------------------- /tests/Kdefconfig_existent_but_n: -------------------------------------------------------------------------------- 1 | # $FOO is "defconfig_2" 2 | # Should produce None due to the "depends on n" 3 | 4 | config A 5 | string 6 | depends on n 7 | option defconfig_list 8 | default "Kconfiglib/tests/defconfig_1" if y && !n && n 9 | default "Kconfiglib/tests/$FOO" 10 | default "Kconfiglib/tests/defconfig_1" 11 | -------------------------------------------------------------------------------- /tests/Kdefconfig_nonexistent: -------------------------------------------------------------------------------- 1 | config A 2 | string 3 | option defconfig_list 4 | default "Kconfiglib/tests/non_existent_1" 5 | default "Kconfiglib/tests/non_existent_2" 6 | -------------------------------------------------------------------------------- /tests/Kdefconfig_srctree: -------------------------------------------------------------------------------- 1 | config A 2 | string 3 | option defconfig_list 4 | default "sub/defconfig_in_sub" # Assume this doesn't exist 5 | default "Kconfiglib/tests/defconfig_2" 6 | -------------------------------------------------------------------------------- /tests/Kdepcopy: -------------------------------------------------------------------------------- 1 | # We verify that the properties below end up in definition order 2 | 3 | config MULTIDEF 4 | bool 5 | default A 6 | default B 7 | select AA 8 | imply AA 9 | 10 | if FOO 11 | 12 | config MULTIDEF 13 | default C 14 | default D 15 | select BB 16 | imply BB 17 | 18 | if BAR 19 | 20 | config MULTIDEF 21 | default E 22 | default F 23 | select CC 24 | imply CC 25 | 26 | menu "menu" 27 | 28 | config MULTIDEF 29 | default G 30 | default H 31 | select DD 32 | imply DD 33 | 34 | config MULTIDEF 35 | default I 36 | default J 37 | select EE 38 | imply EE 39 | 40 | endmenu 41 | 42 | config MULTIDEF 43 | default K 44 | default L 45 | select FF 46 | imply FF 47 | 48 | config MULTIDEF 49 | default M 50 | default N 51 | select GG 52 | imply GG 53 | 54 | endif 55 | 56 | config MULTIDEF 57 | default O 58 | default P 59 | select HH 60 | select II 61 | imply HH 62 | imply II 63 | 64 | endif 65 | 66 | config MULTIDEF 67 | default Q 68 | default R 69 | select JJ 70 | imply JJ 71 | 72 | 73 | # Same test with choice symbols involved 74 | 75 | config MULTIDEF_CHOICE 76 | bool 77 | select A 78 | 79 | choice 80 | bool "choice" 81 | 82 | config MULTIDEF_CHOICE 83 | bool "multidef choice" 84 | select B 85 | 86 | endchoice 87 | 88 | config MULTIDEF_CHOICE 89 | bool 90 | select C 91 | 92 | 93 | # Same test with ranges involved 94 | 95 | config MULTIDEF_RANGE 96 | int 97 | range A _ 98 | 99 | menu "menu" 100 | 101 | config MULTIDEF_RANGE 102 | int 103 | range B _ 104 | 105 | if FOO 106 | 107 | config MULTIDEF_RANGE 108 | int 109 | range C _ 110 | 111 | endif 112 | 113 | config MULTIDEF_RANGE 114 | int 115 | range D _ 116 | 117 | endmenu 118 | 119 | config MULTIDEF_RANGE 120 | int 121 | range E _ 122 | 123 | config MULTIDEF_RANGE 124 | int 125 | range F _ 126 | 127 | 128 | # Same test for a choice 129 | 130 | choice MULTICHOICE 131 | bool "choice" 132 | default A 133 | 134 | config A 135 | bool "A" 136 | 137 | config B 138 | bool "B" 139 | 140 | config C 141 | bool "C" 142 | 143 | config D 144 | bool "C" 145 | 146 | config E 147 | bool "C" 148 | 149 | endchoice 150 | 151 | if FOO 152 | 153 | choice MULTICHOICE 154 | default B 155 | endchoice 156 | 157 | menu "menu" 158 | 159 | choice MULTICHOICE 160 | default C 161 | endchoice 162 | 163 | endmenu 164 | 165 | choice MULTICHOICE 166 | default D 167 | endchoice 168 | 169 | endif 170 | 171 | choice MULTICHOICE 172 | default E 173 | endchoice 174 | -------------------------------------------------------------------------------- /tests/Kdeploop0: -------------------------------------------------------------------------------- 1 | config FOO 2 | bool 3 | depends on FOO 4 | -------------------------------------------------------------------------------- /tests/Kdeploop1: -------------------------------------------------------------------------------- 1 | config FOO 2 | bool 3 | select FOO 4 | -------------------------------------------------------------------------------- /tests/Kdeploop10: -------------------------------------------------------------------------------- 1 | config A 2 | bool 3 | depends on B 4 | 5 | config B 6 | bool 7 | depends on C = 7 8 | 9 | config C 10 | int 11 | range D 8 12 | 13 | config D 14 | int 15 | default 3 if E 16 | default 8 17 | 18 | config E 19 | bool 20 | 21 | config F 22 | bool 23 | select E if G 24 | 25 | config G 26 | bool 27 | depends on H 28 | 29 | choice 30 | bool "choice" 31 | 32 | config H 33 | bool "H" 34 | depends on I 35 | 36 | endchoice 37 | 38 | choice 39 | bool "choice" if J 40 | 41 | config I 42 | bool "I" 43 | 44 | endchoice 45 | 46 | config J 47 | bool 48 | depends on A 49 | -------------------------------------------------------------------------------- /tests/Kdeploop2: -------------------------------------------------------------------------------- 1 | config FOO 2 | bool 3 | default FOO 4 | -------------------------------------------------------------------------------- /tests/Kdeploop3: -------------------------------------------------------------------------------- 1 | config FOO 2 | bool 3 | default y if FOO 4 | -------------------------------------------------------------------------------- /tests/Kdeploop4: -------------------------------------------------------------------------------- 1 | config FOO 2 | bool 3 | depends on BAR 4 | 5 | config BAR 6 | bool 7 | depends on FOO 8 | -------------------------------------------------------------------------------- /tests/Kdeploop5: -------------------------------------------------------------------------------- 1 | config FOO 2 | bool 3 | select BAR 4 | 5 | config BAR 6 | bool 7 | select FOO 8 | -------------------------------------------------------------------------------- /tests/Kdeploop6: -------------------------------------------------------------------------------- 1 | config FOO 2 | bool 3 | 4 | config BAR 5 | bool 6 | select FOO if FOO 7 | -------------------------------------------------------------------------------- /tests/Kdeploop7: -------------------------------------------------------------------------------- 1 | choice 2 | bool "choice" 3 | 4 | config FOO 5 | bool "foo" 6 | depends on BAR 7 | 8 | config BAR 9 | bool "bar" 10 | 11 | endchoice 12 | -------------------------------------------------------------------------------- /tests/Kdeploop8: -------------------------------------------------------------------------------- 1 | choice 2 | bool "choice" 3 | default FOO if FOO 4 | 5 | config FOO 6 | bool "foo" 7 | 8 | endchoice 9 | -------------------------------------------------------------------------------- /tests/Kdeploop9: -------------------------------------------------------------------------------- 1 | choice 2 | bool "choice" if FOO 3 | 4 | config FOO 5 | bool "foo" 6 | 7 | endchoice 8 | -------------------------------------------------------------------------------- /tests/Kdirdep: -------------------------------------------------------------------------------- 1 | config NO_DEP_SYM 2 | bool 3 | 4 | config DEP_SYM 5 | bool 6 | depends on A 7 | 8 | config DEP_SYM 9 | depends on B && C 10 | 11 | config DEP_SYM 12 | depends on !D 13 | 14 | 15 | choice NO_DEP_CHOICE 16 | bool "no dep. choice" 17 | endchoice 18 | 19 | choice DEP_CHOICE 20 | bool "dep. choice" 21 | depends on A 22 | endchoice 23 | 24 | choice DEP_CHOICE 25 | depends on B 26 | endchoice 27 | 28 | choice DEP_CHOICE 29 | depends on C 30 | endchoice 31 | -------------------------------------------------------------------------------- /tests/Kescape: -------------------------------------------------------------------------------- 1 | config STRING 2 | string "string" 3 | default "\"\\" 4 | -------------------------------------------------------------------------------- /tests/Keval: -------------------------------------------------------------------------------- 1 | # Enabled/disabled in the test 2 | config MODULES 3 | bool "modules" 4 | option modules 5 | 6 | config N 7 | def_tristate n 8 | 9 | config M 10 | def_tristate m 11 | 12 | menuconfig Y 13 | def_tristate y 14 | prompt "foo" 15 | 16 | config Y_STRING 17 | string 18 | default "y" 19 | 20 | config FOO_BAR_STRING 21 | string 22 | default "foo bar" 23 | 24 | config INT_37 25 | int 26 | default 37 27 | 28 | config HEX_0X37 29 | hex 30 | default 0x37 31 | 32 | config HEX_37 33 | hex 34 | default 37 35 | -------------------------------------------------------------------------------- /tests/Kexpr_items: -------------------------------------------------------------------------------- 1 | config TEST 2 | bool 3 | default A && (B || !C && D = "E") || F > G || !!!H 4 | 5 | choice CHOICE 6 | bool "choice" 7 | 8 | config TEST_CHOICE 9 | bool "test choice" if A 10 | 11 | endchoice 12 | -------------------------------------------------------------------------------- /tests/Kheader: -------------------------------------------------------------------------------- 1 | # Used to test headers in .config and header files 2 | 3 | config FOO 4 | bool "foo" 5 | default y 6 | -------------------------------------------------------------------------------- /tests/Khelp: -------------------------------------------------------------------------------- 1 | config TWO_HELP_STRINGS 2 | bool 3 | help 4 | first help string 5 | 6 | 7 | 8 | 9 | config TWO_HELP_STRINGS 10 | help 11 | second help string 12 | 13 | config NO_BLANK_AFTER_HELP 14 | bool 15 | help 16 | help for 17 | NO_BLANK_AFTER_HELP 18 | choice CHOICE_HELP 19 | bool "choice with help" 20 | help 21 | help for 22 | CHOICE_HELP 23 | endchoice 24 | 25 | config HELP_TERMINATED_BY_COMMENT 26 | bool 27 | help 28 | a 29 | b 30 | c 31 | # 32 | 33 | config TRICKY_HELP 34 | bool 35 | -help--- 36 | 37 | 38 | a 39 | b 40 | c 41 | 42 | d 43 | e 44 | f 45 | 46 | 47 | g 48 | h 49 | i 50 | # 51 | -------------------------------------------------------------------------------- /tests/Kifremoval: -------------------------------------------------------------------------------- 1 | # Test some tricky cases that give consecutive 'if' nodes even after 2 | # flattening. Simple cases are exercised a ton elsewhere. 3 | 4 | if X 5 | endif 6 | if X 7 | endif 8 | 9 | config A 10 | 11 | if X 12 | endif 13 | if X 14 | endif 15 | 16 | config B 17 | 18 | if X 19 | endif 20 | if X 21 | endif 22 | if X 23 | endif 24 | 25 | config C 26 | 27 | if X 28 | if X 29 | if X 30 | endif 31 | if X 32 | endif 33 | endif 34 | if X 35 | if X 36 | endif 37 | if X 38 | endif 39 | endif 40 | config D 41 | endif 42 | if X 43 | endif 44 | 45 | menu "E" 46 | if X 47 | if X 48 | endif 49 | endif 50 | if X 51 | if X 52 | endif 53 | endif 54 | endmenu 55 | 56 | menu "F" 57 | if X 58 | endif 59 | if X 60 | endif 61 | if X 62 | if X 63 | endif 64 | if X 65 | endif 66 | menu "G" 67 | endmenu 68 | endif 69 | endmenu 70 | 71 | choice H 72 | if X 73 | if X 74 | endif 75 | endif 76 | if X 77 | if X 78 | endif 79 | endif 80 | endchoice 81 | 82 | choice I 83 | if X 84 | endif 85 | if X 86 | endif 87 | if X 88 | if X 89 | endif 90 | if X 91 | endif 92 | config J 93 | endif 94 | endchoice 95 | 96 | if X 97 | endif 98 | if X 99 | endif 100 | -------------------------------------------------------------------------------- /tests/Kimply: -------------------------------------------------------------------------------- 1 | config MODULES 2 | def_bool y 3 | option modules 4 | 5 | # 6 | # Implied symbols with unmet and met direct dependencies 7 | # 8 | 9 | config IMPLY_DIRECT_DEPS 10 | def_tristate y 11 | imply UNMET_DIRECT_1 12 | imply UNMET_DIRECT_2 13 | imply UNMET_DIRECT_3 14 | imply MET_DIRECT_1 15 | imply MET_DIRECT_2 16 | imply MET_DIRECT_3 17 | imply MET_DIRECT_4 18 | 19 | config UNMET_DIRECT_1 20 | tristate 21 | depends on n 22 | 23 | if n 24 | config UNMET_DIRECT_2 25 | tristate 26 | endif 27 | 28 | menu "menu" 29 | depends on n 30 | 31 | config UNMET_DIRECT_3 32 | tristate 33 | 34 | endmenu 35 | 36 | config MET_DIRECT_1 37 | tristate 38 | 39 | config MET_DIRECT_2 40 | depends on y 41 | tristate 42 | 43 | if y 44 | config MET_DIRECT_3 45 | tristate 46 | endif 47 | 48 | menu "menu" 49 | depends on y 50 | 51 | config MET_DIRECT_4 52 | tristate 53 | 54 | endmenu 55 | 56 | # 57 | # 'imply' with condition 58 | # 59 | 60 | config IMPLY_COND 61 | def_tristate y 62 | tristate 63 | imply IMPLIED_N_COND if n 64 | imply IMPLIED_M_COND if m 65 | imply IMPLIED_Y_COND if y 66 | 67 | config IMPLIED_N_COND 68 | tristate 69 | 70 | config IMPLIED_M_COND 71 | tristate 72 | 73 | config IMPLIED_Y_COND 74 | tristate 75 | 76 | # 77 | # Implying from symbol with value n 78 | # 79 | 80 | # Will default to 'n' 81 | config IMPLY_N_1 82 | tristate 83 | imply IMPLIED_FROM_N_1 84 | 85 | # This test also disables the imply, so it's kinda redundant, but why not 86 | if n 87 | config IMPLY_N_2 88 | tristate 89 | imply IMPLIED_FROM_N_2 90 | endif 91 | 92 | config IMPLIED_FROM_N_1 93 | tristate 94 | 95 | config IMPLIED_FROM_N_2 96 | tristate 97 | 98 | # 99 | # Implying from symbol with value m 100 | # 101 | 102 | config IMPLY_M 103 | def_tristate m 104 | imply IMPLIED_M 105 | # Implying a bool to 'm' makes it default to 'y' 106 | imply IMPLIED_M_BOOL 107 | 108 | config IMPLIED_M 109 | tristate 110 | 111 | config IMPLIED_M_BOOL 112 | bool 113 | 114 | # 115 | # 'imply' which should raise an 'm' default to 'y' 116 | # 117 | 118 | config IMPLY_M_TO_Y 119 | tristate 120 | default y 121 | imply IMPLIED_M_TO_Y 122 | 123 | config IMPLIED_M_TO_Y 124 | tristate 125 | default m 126 | 127 | # 128 | # Used for testing user values 129 | # 130 | 131 | config DIRECT_DEP 132 | tristate "direct dep" 133 | 134 | config IMPLY 135 | tristate "imply" 136 | imply IMPLIED_TRISTATE 137 | imply IMPLIED_BOOL 138 | 139 | config IMPLIED_TRISTATE 140 | tristate "implied tristate" 141 | depends on DIRECT_DEP 142 | 143 | config IMPLIED_BOOL 144 | bool "implied bool" 145 | depends on DIRECT_DEP 146 | -------------------------------------------------------------------------------- /tests/Kinclude_path: -------------------------------------------------------------------------------- 1 | config TOP 2 | bool 3 | 4 | source "Kinclude_path_sourced_1" 5 | 6 | config TOP 7 | bool 8 | 9 | source "Kinclude_path_sourced_1" 10 | 11 | config TOP 12 | bool 13 | -------------------------------------------------------------------------------- /tests/Kinclude_path_sourced_1: -------------------------------------------------------------------------------- 1 | config ONE_DOWN 2 | bool 3 | 4 | source "Kinclude_path_sourced_2" 5 | 6 | config ONE_DOWN 7 | bool 8 | 9 | source "Kinclude_path_sourced_2" 10 | 11 | config ONE_DOWN 12 | bool 13 | -------------------------------------------------------------------------------- /tests/Kinclude_path_sourced_2: -------------------------------------------------------------------------------- 1 | config TWO_DOWN 2 | bool 3 | 4 | menu "menu" 5 | endmenu 6 | 7 | comment "comment" 8 | 9 | choice 10 | bool "choice" 11 | endchoice 12 | -------------------------------------------------------------------------------- /tests/Kitemlists: -------------------------------------------------------------------------------- 1 | comment "comment 1" 2 | 3 | choice 4 | bool "choice 1" 5 | endchoice 6 | 7 | menu "menu 1" 8 | 9 | choice NAMED 10 | bool "choice 2" 11 | endchoice 12 | 13 | menu "menu 2" 14 | menu "menu 3" 15 | comment "comment 2" 16 | endmenu 17 | 18 | choice 19 | bool "choice 3" 20 | endchoice 21 | 22 | choice NAMED 23 | bool 24 | endchoice 25 | 26 | endmenu 27 | 28 | menu "menu 4" 29 | endmenu 30 | 31 | comment "comment 3" 32 | 33 | endmenu 34 | 35 | menu "menu 5" 36 | endmenu 37 | -------------------------------------------------------------------------------- /tests/Klocation: -------------------------------------------------------------------------------- 1 | if UNDEFINED 2 | endif 3 | 4 | config ONE_DEF 5 | bool 6 | 7 | config TWO_DEF 8 | bool 9 | 10 | config TWO_DEF 11 | bool 12 | 13 | config MANY_DEF 14 | bool 15 | 16 | # Throw in some line continuations too to make sure it doesn't mess up the line 17 | # numbers 18 | if y && \ 19 | y 20 | if y && \ 21 | y && \ 22 | y 23 | 24 | # Throw in some help texts too 25 | 26 | config HELP_1 27 | bool "help 1" 28 | help 29 | config HELP_2 30 | bool "help 2" 31 | help 32 | foo 33 | bar 34 | 35 | baz 36 | 37 | config HELP_3 38 | help 39 | foo 40 | bar 41 | bool 42 | config \ 43 | MANY_DEF 44 | 45 | config MANY_DEF 46 | 47 | endif 48 | endif 49 | 50 | # Expands to "tests/Klocation_sourced" 51 | source "$TESTS_DIR_FROM_ENV/Klocation$_SOURCED" 52 | 53 | # Expands to "sub/Klocation_rsourced" 54 | rsource "$SUB_DIR_FROM_ENV/Klocation$_RSOURCED" 55 | 56 | # Expands to "tests/*ub/Klocation_gsourced[12]", matching 57 | # tests/sub/Klocation_gsourced{1,2} 58 | source "$TESTS_DIR_FROM_ENV/*ub/Klocation$_GSOURCED[12]" 59 | # Test old syntax too 60 | gsource "$TESTS_DIR_FROM_ENV/*ub/Klocation$_GSOURCED[12]" 61 | 62 | # Expands to "sub/Klocation_grsourced[12]", matching 63 | # tests/sub/Klocation_grsourced{1,2} 64 | rsource "$SUB_DIR_FROM_ENV/Klocation$_GRSOURCED[12]" 65 | # Test old syntax too 66 | grsource "$SUB_DIR_FROM_ENV/Klocation$_GRSOURCED[12]" 67 | 68 | # No-ops 69 | osource "nonexistent" 70 | osource "nonexistent*" 71 | gsource "nonexistent" 72 | gsource "nonexistent*" 73 | orsource "nonexistent" 74 | orsource "nonexistent*" 75 | grsource "nonexistent" 76 | grsource "nonexistent*" 77 | 78 | config MANY_DEF 79 | -------------------------------------------------------------------------------- /tests/Klocation_sourced: -------------------------------------------------------------------------------- 1 | 2 | 3 | config MANY_DEF 4 | 5 | choice CHOICE_ONE_DEF 6 | bool "one-def choice" 7 | endchoice 8 | 9 | choice CHOICE_TWO_DEF 10 | bool "two-def choice 1" 11 | endchoice 12 | 13 | choice CHOICE_TWO_DEF 14 | bool "two-def choice 2" 15 | endchoice 16 | 17 | config MENU_HOOK 18 | bool 19 | 20 | menu "menu" 21 | endmenu 22 | 23 | config COMMENT_HOOK 24 | bool 25 | 26 | comment "comment" 27 | -------------------------------------------------------------------------------- /tests/Kmainmenu: -------------------------------------------------------------------------------- 1 | config FOO 2 | string 3 | option env="FOO" 4 | 5 | mainmenu "---$FOO---" 6 | -------------------------------------------------------------------------------- /tests/Kmenuconfig: -------------------------------------------------------------------------------- 1 | # Menu nodes with is_menuconfig False 2 | 3 | config NOT_MENUCONFIG_1 4 | bool 5 | 6 | config NOT_MENUCONFIG_2 7 | bool "not menuconfig 2" 8 | 9 | config MENUCONFIG_MULTI_DEF 10 | bool "menuconfig multi def 1" 11 | 12 | config COMMENT_HOOK 13 | bool 14 | 15 | comment "not menuconfig 3" 16 | 17 | 18 | # Menu nodes with is_menuconfig True 19 | 20 | menuconfig MENUCONFIG_1 21 | bool "menuconfig 1" 22 | 23 | menuconfig MENUCONFIG_MULTI_DEF 24 | bool "menuconfig multi def 2" 25 | 26 | config MENU_HOOK 27 | bool 28 | 29 | menu "menuconfig 2" 30 | endmenu 31 | 32 | config CHOICE_HOOK 33 | bool 34 | 35 | choice 36 | bool "menuconfig 3" 37 | endchoice 38 | -------------------------------------------------------------------------------- /tests/Kmisc: -------------------------------------------------------------------------------- 1 | # For testing various minor APIs 2 | 3 | # optional choices 4 | 5 | choice NOT_OPTIONAL 6 | bool "not optional" 7 | config A 8 | bool "A" 9 | config B 10 | bool "B" 11 | endchoice 12 | 13 | choice OPTIONAL 14 | tristate "optional" 15 | optional 16 | config C 17 | tristate "C" 18 | config D 19 | tristate "D" 20 | # Quirky symbols - not proper choice symbol 21 | 22 | config Q1 23 | tristate "Q1" 24 | depends on D 25 | 26 | config Q2 27 | tristate "Q2" 28 | depends on Q1 29 | 30 | config Q3 31 | tristate "Q3" 32 | depends on D 33 | 34 | endchoice 35 | 36 | # User values 37 | 38 | config BOOL 39 | bool "bool" if NOT_DEFINED_1 40 | 41 | config TRISTATE 42 | tristate # Visibility should not affect user value 43 | 44 | config STRING 45 | string "string" 46 | 47 | config INT 48 | int # Visibility should not affect user value 49 | 50 | config HEX 51 | hex "hex" 52 | depends on NOT_DEFINED_2 53 | 54 | config COMMENT_HOOK 55 | comment "comment" 56 | 57 | config MENU_HOOK 58 | menu "menu" 59 | depends on NOT_DEFINED_3 || NOT_DEFINED_2 60 | depends on !NOT_DEFINED_4 61 | endmenu 62 | 63 | config FROM_ENV 64 | string "from env" 65 | option env="ENV_VAR" 66 | 67 | config FROM_ENV_MISSING 68 | string "from env missing" 69 | option env="MISSING_ENV_VAR" 70 | default "missing" 71 | 72 | config FROM_ENV_WEIRD 73 | string 74 | default "weird" 75 | option env="ENV_VAR" 76 | 77 | config NOT_ALLNOCONFIG_Y 78 | bool "not allnoconfig_y" 79 | 80 | config ALLNOCONFIG_Y 81 | bool "allnoconfig_y" 82 | option allnoconfig_y 83 | -------------------------------------------------------------------------------- /tests/Kmissingrsource: -------------------------------------------------------------------------------- 1 | rsource "nonexistent" 2 | -------------------------------------------------------------------------------- /tests/Kmissingsource: -------------------------------------------------------------------------------- 1 | source "nonexistent" 2 | -------------------------------------------------------------------------------- /tests/Korder: -------------------------------------------------------------------------------- 1 | config O 2 | int "O" 3 | default 0 4 | 5 | config R 6 | int "R" 7 | default 1 8 | 9 | config D 10 | int "D" 11 | default 2 12 | 13 | config E 14 | int "E" 15 | default 3 16 | 17 | # Defined twice 18 | config R 19 | int "R" 20 | 21 | config R2 22 | int "R2" 23 | default 4 24 | 25 | config I 26 | int "I" 27 | default 5 28 | 29 | config N 30 | int "N" 31 | default 6 32 | 33 | config G 34 | int "G" 35 | default 7 36 | -------------------------------------------------------------------------------- /tests/Kpreprocess: -------------------------------------------------------------------------------- 1 | # Simple assignments (with bad formatting, as an additional test) 2 | 3 | simple-recursive=foo 4 | simple-immediate:=bar 5 | # Should become recursive 6 | simple-recursive-2+=baz 7 | 8 | whitespaced = foo 9 | 10 | 11 | # Simple += test. += should preserve the flavor of the variable (simple vs. 12 | # recursive). 13 | 14 | preserve-recursive = foo 15 | preserve-recursive += bar 16 | 17 | preserve-immediate := foo 18 | preserve-immediate += bar 19 | 20 | 21 | # Recursive substitution 22 | 23 | recursive = $(foo) $(bar) $($(b-char)a$(z-char)) 24 | recursive += $(indir) 25 | 26 | foo = abc 27 | bar = def 28 | baz = ghi 29 | 30 | b-char = b 31 | z-char = z 32 | 33 | indir = jkl $(indir-2) 34 | indir-2 = mno 35 | 36 | 37 | # Immediate substitution 38 | 39 | def = foo 40 | immediate := $(undef)$(def)$(undef)$(def) 41 | def = bar 42 | undef = bar 43 | 44 | 45 | # Function calls 46 | 47 | # Chained function call 48 | quote = "$(1)" "$(2)" 49 | rev-quote = $(quote,$(2),$(1)) 50 | surround-rev-quote = $(0) $(rev-quote,$(1),$(2)) $(0) 51 | surround-rev-quote-unused-arg = $(surround-rev-quote,$(1),$(2)) $(3) 52 | # No value is passed for $(3), so it expands to nothing 53 | fn-indir = surround-rev-quote 54 | messy-fn-res = $($(fn-indir)-unused-arg, a b (,) , c d ) 55 | 56 | # Special characters in function call 57 | comma = , 58 | right-paren = ) 59 | dollar = $ 60 | left-paren = ( 61 | fn = "$(1)" 62 | special-chars-fn-res = $(fn,$(comma)$(dollar)$(left-paren)foo$(right-paren)) 63 | 64 | 65 | # Variable expansions in various locations (verified by checking how the symbol 66 | # prints) 67 | 68 | qaz = QAZ 69 | echo = $(1) 70 | ignore-first = $(2) 71 | 72 | config PRINT_ME 73 | string "$(ENV_1)" if ($(echo,FOO) && $(echo,BAR)) || !$(echo,BAZ) || !(($(qaz))) 74 | default "$(echo,"foo")" if "foo $(echo,"bar") baz" = "$(undefined)" 75 | 76 | # Expansion within a symbol token, with deliberate sloppiness 77 | config PRINT_$(ignore-first, ,ME)_TOO 78 | bool "foo" 79 | default FOO$(ignore-first, ,BAR)BAZ$(qaz) if $(qaz)&&$(qaz)FOO&&x$(ignore-first, ,xx) 80 | 81 | 82 | # Recursive expansion (throws an exception) 83 | 84 | rec-1 = x $(rec-2) y 85 | rec-2 = x $(rec-3) y 86 | rec-3 = x $(rec-1) y 87 | 88 | # Functions are allowed to reference themselves, but an exception is thrown if 89 | # the function seems to be stuck (the recursion gets too deep) 90 | safe-fn-rec = $($(1)) 91 | safe-fn-rec-2 = $(safe-fn-rec,safe-fn-rec-3) 92 | safe-fn-rec-3 = foo 93 | safe-fn-rec-res = $(safe-fn-rec,safe-fn-rec-2) 94 | 95 | unsafe-fn-rec = $(unsafe-fn-rec,$(1)) 96 | 97 | 98 | # Expansion in the left-hand side of assignments 99 | 100 | dummy-arg-fn = bar 101 | lhs-indir-1 = lhs-indir-2 102 | lhs-indir-2 = -baz 103 | rhs = value 104 | # LHS expands to foo-bar-baz 105 | foo-$(dummy-arg-fn, ignored argument )$($(lhs-indir-1)) = $(rhs) 106 | # Expands to empty string, accepted 107 | $(undefined) 108 | 109 | # Variable with a space in its name 110 | empty = 111 | space = $(empty) $(empty) 112 | foo$(space)bar = value 113 | space-var-res = $(foo bar) 114 | 115 | 116 | # Built-in functions 117 | 118 | # Expands to "baz qaz" 119 | shell-res = $(shell,false && echo foo bar || echo baz qaz) 120 | 121 | # Warns about output on stderr, expands to nothing 122 | shell-stderr-res := $(shell,echo message on stderr >&2) 123 | 124 | # Nested parens in macro call. Should give a single argument. Test it with 125 | # $(shell) to get a free argument number check. 126 | parens-res = pre-$(shell,echo '(a,$(b-char),(c,d),e)')-post 127 | 128 | # Expands to the current location 129 | location-res := $(filename):$(lineno) 130 | 131 | # Adds one warning, expands to nothing 132 | $(warning-if,,no warning) 133 | $(warning-if,n,no warning) 134 | warning-res := $(warning-if,y,a warning) 135 | 136 | # Does not cause an error, expands to nothing 137 | error-n-res := $(error-if,n,oops) 138 | 139 | # Causes an error when expanded 140 | error-y-res = $(error-if,y,oops) 141 | 142 | 143 | # Environment variables (for testing Kconfig.env_vars). ENV_1 is already 144 | # referenced above. 145 | env_ref_1 := xxx $(ENV_2) xxx 146 | env_ref_2 := $(shell,echo $(ENV_3)) 147 | env_ref_3 := 148 | env_ref_3 += $(ENV_4) 149 | $(warning-if,$(ENV_5),$(ENV_UNDEFINED)) 150 | source "$(ENV_6)" 151 | env_ref_4 = $(ENV_7) # Never evaluated 152 | -------------------------------------------------------------------------------- /tests/Krange: -------------------------------------------------------------------------------- 1 | # 2 | # No ranges 3 | # 4 | 5 | config HEX_NO_RANGE 6 | hex "hex no range" 7 | 8 | config INT_NO_RANGE 9 | int "int no range" 10 | 11 | # 12 | # Disabled ranges 13 | # 14 | 15 | config HEX_ALL_RANGES_DISABLED 16 | hex "hex all ranges disabled" 17 | range 0x10 0x20 if n 18 | range 0x30 0x40 if n 19 | 20 | config INT_ALL_RANGES_DISABLED 21 | int "int all ranges disabled" 22 | range 10 20 if n 23 | range 30 40 if n 24 | 25 | # 26 | # Ranges with defaults 27 | # 28 | 29 | # hex 30 | 31 | config HEX_RANGE_10_20_LOW_DEFAULT 32 | hex "int range 10-20 low default" 33 | range 0x10 0x20 34 | default 0x9 35 | 36 | config HEX_RANGE_10_20_HIGH_DEFAULT 37 | hex "int range 10-20 high default" 38 | range 0x10 0x20 39 | default 0x21 40 | 41 | config HEX_RANGE_10_20_OK_DEFAULT 42 | hex "int range 10-20 ok default" 43 | range 0x10 0x20 44 | default 0x15 45 | 46 | config HEX_RANGE_10_20_OK_DEFAULT_ALTERNATE 47 | hex "int range 10-20 ok default alternate" 48 | range 0x10 0x20 49 | default 15 50 | 51 | # int 52 | 53 | config INT_RANGE_10_20_LOW_DEFAULT 54 | int "int range 10-20 low default" 55 | range 10 20 56 | default 9 57 | 58 | config INT_RANGE_10_20_HIGH_DEFAULT 59 | int "int range 10-20 high default" 60 | range 10 20 61 | default 21 62 | 63 | config INT_RANGE_10_20_OK_DEFAULT 64 | int "int range 10-20 ok default" 65 | range 10 20 66 | default 15 67 | 68 | # 69 | # Ranges with no defaults (should default to low end of range if > 0) 70 | # 71 | 72 | config HEX_RANGE_10_20 73 | hex "hex range 10-20" 74 | range 0x10 0x20 75 | 76 | config HEX_RANGE_0_10 77 | hex "hex range 0-10" 78 | range 0x0 0x10 79 | 80 | config INT_RANGE_10_20 81 | int "int range 10-20" 82 | range 10 20 83 | 84 | config INT_RANGE_0_10 85 | int "int range 0-10" 86 | range 0 10 87 | 88 | config INT_RANGE_NEG_10_10 89 | int "int range -10-10" 90 | range -10 10 91 | 92 | # 93 | # Dependent ranges 94 | # 95 | 96 | config HEX_40 97 | hex 98 | default 40 99 | 100 | config HEX_RANGE_10_40_DEPENDENT 101 | hex "hex range 10-40 dependent" 102 | range HEX_RANGE_10_20 HEX_40 103 | 104 | config INT_40 105 | int 106 | default 40 107 | 108 | config INT_RANGE_10_40_DEPENDENT 109 | int "int range 10-40 dependent" 110 | range INT_RANGE_10_20 INT_40 111 | 112 | # 113 | # Ranges on symbols defined in multiple locations 114 | # 115 | 116 | if n 117 | config INACTIVE_RANGE 118 | range 0 1 119 | endif 120 | 121 | config INACTIVE_RANGE 122 | int 123 | # Default will apply and should not get clamped, 124 | # because the range does not apply 125 | default 2 126 | 127 | config ACTIVE_RANGE 128 | range 0 1 129 | 130 | config ACTIVE_RANGE 131 | int 132 | # Default will apply and should be clamped to 1 133 | default 2 134 | -------------------------------------------------------------------------------- /tests/Krecursive1: -------------------------------------------------------------------------------- 1 | source "tests/Krecursive2" 2 | -------------------------------------------------------------------------------- /tests/Krecursive2: -------------------------------------------------------------------------------- 1 | source "tests/Krecursive1" 2 | -------------------------------------------------------------------------------- /tests/Kreferenced: -------------------------------------------------------------------------------- 1 | config NO_REFS 2 | bool 3 | 4 | config JUST_DEPENDS_ON_REFS 5 | bool 6 | depends on A && B 7 | 8 | if A 9 | 10 | menu "menu" 11 | depends on B 12 | visible if C 13 | visible if D 14 | 15 | config LOTS_OF_REFS 16 | bool "lots" if C || D 17 | default E || F if G || H 18 | default I || J if K || L 19 | select M if N || O 20 | select P if Q || R 21 | imply S if T || U 22 | imply V if W || X 23 | depends on Y || Z 24 | 25 | endmenu 26 | 27 | endif 28 | 29 | config INT_REFS 30 | int "int" 31 | range A B if C && D 32 | range E F if G && H 33 | 34 | choice CHOICE 35 | bool "choice" 36 | 37 | config CHOICE_REF 38 | bool "choice ref" 39 | 40 | endchoice 41 | 42 | comment "comment" 43 | depends on A || B 44 | 45 | 46 | config MULTI_DEF_SYM 47 | def_bool A && B 48 | 49 | config MULTI_DEF_SYM 50 | depends on C 51 | 52 | 53 | choice MULTI_DEF_CHOICE 54 | bool "choice" 55 | depends on A && B 56 | 57 | endchoice 58 | 59 | choice MULTI_DEF_CHOICE 60 | bool "choice" 61 | depends on C 62 | 63 | endchoice 64 | -------------------------------------------------------------------------------- /tests/Krelation: -------------------------------------------------------------------------------- 1 | config A 2 | bool 3 | depends on UNDEFINED 4 | 5 | choice CHOICE_1 6 | bool "C" 7 | config B 8 | bool "B" 9 | config C 10 | bool "C" if B 11 | config D 12 | bool "D" 13 | endchoice 14 | 15 | menu "m1" 16 | config E 17 | bool 18 | menu "m2" 19 | config F 20 | bool 21 | choice CHOICE_2 22 | tristate "foo" 23 | config G 24 | bool "g" 25 | config H 26 | bool "h" 27 | endchoice 28 | endmenu 29 | config I 30 | bool 31 | endmenu 32 | 33 | menu "m3" 34 | endmenu 35 | menu "m4" 36 | endmenu 37 | -------------------------------------------------------------------------------- /tests/Krepr: -------------------------------------------------------------------------------- 1 | config MODULES 2 | bool 3 | option modules 4 | default y 5 | 6 | if UNDEFINED 7 | endif 8 | 9 | config BASIC 10 | bool 11 | default y 12 | ---help--- 13 | 14 | config VISIBLE 15 | bool "visible" 16 | 17 | config STRING 18 | string "visible" 19 | 20 | config DIR_DEP_N 21 | depends on n 22 | 23 | config OPTIONS 24 | option allnoconfig_y 25 | option defconfig_list 26 | option env="ENV" 27 | 28 | config MULTI_DEF 29 | config MULTI_DEF 30 | 31 | menuconfig MENUCONFIG 32 | 33 | choice CHOICE 34 | tristate "choice" 35 | 36 | config CHOICE_1 37 | tristate "choice sym" 38 | 39 | config CHOICE_2 40 | tristate "choice sym" 41 | 42 | endchoice 43 | 44 | config CHOICE_HOOK 45 | 46 | choice 47 | tristate "optional choice" if n 48 | optional 49 | endchoice 50 | 51 | config NO_VISIBLE_IF_HOOK 52 | 53 | menu "no visible if" 54 | endmenu 55 | 56 | config VISIBLE_IF_HOOK 57 | 58 | menu "visible if" 59 | visible if m 60 | endmenu 61 | 62 | config COMMENT_HOOK 63 | 64 | comment "comment" 65 | -------------------------------------------------------------------------------- /tests/Kstr: -------------------------------------------------------------------------------- 1 | if UNDEFINED 2 | endif 3 | 4 | config NO_TYPE 5 | 6 | config BASIC_NO_PROMPT 7 | bool 8 | help 9 | blah blah 10 | 11 | blah blah blah 12 | 13 | blah 14 | 15 | config BASIC_PROMPT 16 | bool "basic" 17 | 18 | config ADVANCED 19 | tristate "prompt" if DEP 20 | default DEFAULT_1 21 | default DEFAULT_2 if DEP 22 | select SELECTED_1 23 | select SELECTED_2 if DEP 24 | imply IMPLIED_1 25 | imply IMPLIED_2 if DEP 26 | help 27 | first help text 28 | 29 | config ADVANCED 30 | prompt "prompt 2" 31 | 32 | menuconfig ADVANCED 33 | prompt "prompt 3" 34 | 35 | if DEP3 36 | 37 | menu "foo" 38 | depends on DEP4 39 | visible if VIS 40 | 41 | config ADVANCED 42 | help 43 | second help text 44 | depends on A || !B || (C && D) || !(E && F) || G = H || \ 45 | (I && !J && (K || L) && !(M || N) && O = P) 46 | 47 | config ADVANCED 48 | # Used to verify that the direct dependencies appear to the right of VIS 49 | prompt "prompt 4" 50 | 51 | endmenu 52 | 53 | endif 54 | 55 | config ONLY_DIRECT_DEPS 56 | int 57 | depends on DEP1 58 | depends on DEP2 59 | 60 | config STRING 61 | def_string "foo" 62 | default "bar" if DEP 63 | default STRING2 64 | default STRING3 if DEP 65 | 66 | config INT 67 | def_int 7 if DEP 68 | range 1 2 69 | range FOO BAR 70 | range BAZ QAZ if DEP 71 | 72 | config HEX 73 | def_hex 0x123 74 | range 0x100 0x200 75 | range FOO BAR 76 | range BAZ QAZ if DEP 77 | 78 | config MODULES 79 | bool "MODULES" 80 | option modules 81 | 82 | config OPTIONS 83 | option allnoconfig_y 84 | option defconfig_list 85 | option env="ENV" 86 | 87 | if LOC_1 88 | config CORRECT_PROP_LOCS_BOOL 89 | prompt "prompt 1" 90 | default DEFAULT_1 91 | default DEFAULT_2 92 | select SELECT_1 93 | select SELECT_2 94 | imply IMPLY_1 95 | imply IMPLY_2 96 | help 97 | help 1 98 | endif 99 | 100 | if LOC_2 101 | menuconfig CORRECT_PROP_LOCS_BOOL 102 | bool "prompt 2" 103 | default DEFAULT_3 104 | default DEFAULT_4 105 | select SELECT_3 106 | select SELECT_4 107 | imply IMPLY_3 108 | imply IMPLY_4 109 | help 110 | help 2 111 | endif 112 | 113 | if LOC_3 114 | config CORRECT_PROP_LOCS_BOOL 115 | prompt "prompt 3" 116 | default DEFAULT_5 117 | default DEFAULT_6 118 | select SELECT_5 119 | select SELECT_6 120 | imply IMPLY_5 121 | imply IMPLY_6 122 | help 123 | help 2 124 | endif 125 | 126 | if LOC_1 127 | config CORRECT_PROP_LOCS_INT 128 | int 129 | range 1 2 130 | range 3 4 131 | endif 132 | 133 | if LOC_2 134 | config CORRECT_PROP_LOCS_INT 135 | range 5 6 136 | range 7 8 137 | endif 138 | 139 | choice CHOICE 140 | tristate "foo" 141 | default CHOICE_1 142 | default CHOICE_2 if dep 143 | 144 | config CHOICE_1 145 | tristate "choice 1" 146 | 147 | config CHOICE_2 148 | tristate "choice 2" 149 | 150 | endchoice 151 | 152 | choice 153 | tristate "no name" 154 | optional 155 | endchoice 156 | 157 | if LOC_1 158 | choice CORRECT_PROP_LOCS_CHOICE 159 | bool 160 | default CHOICE_3 161 | 162 | config CHOICE_3 163 | bool "choice 3" 164 | 165 | config CHOICE_4 166 | bool "choice 3" 167 | 168 | config CHOICE_5 169 | bool "choice 3" 170 | 171 | endchoice 172 | endif 173 | 174 | if LOC_2 175 | choice CORRECT_PROP_LOCS_CHOICE 176 | default CHOICE_4 177 | endchoice 178 | endif 179 | 180 | if LOC_3 181 | choice CORRECT_PROP_LOCS_CHOICE 182 | default CHOICE_5 183 | endchoice 184 | endif 185 | 186 | config SIMPLE_MENU_HOOK 187 | menu "simple menu" 188 | endmenu 189 | 190 | config ADVANCED_MENU_HOOK 191 | menu "advanced menu" 192 | depends on A 193 | visible if B 194 | visible if C || D 195 | endmenu 196 | 197 | config SIMPLE_COMMENT_HOOK 198 | comment "simple comment" 199 | 200 | config ADVANCED_COMMENT_HOOK 201 | comment "advanced comment" 202 | depends on A 203 | depends on B 204 | 205 | # Corner cases when removing direct dependencies 206 | 207 | config DEP_REM_CORNER_CASES 208 | bool 209 | default A 210 | depends on n 211 | 212 | config DEP_REM_CORNER_CASES 213 | default B if n 214 | 215 | config DEP_REM_CORNER_CASES 216 | default C 217 | depends on m 218 | 219 | config DEP_REM_CORNER_CASES 220 | default D if A && y 221 | depends on y 222 | 223 | config DEP_REM_CORNER_CASES 224 | default E if !E1 225 | default F if F1 = F2 226 | default G if G1 || H1 227 | depends on !H 228 | 229 | config DEP_REM_CORNER_CASES 230 | default H 231 | depends on "foo" = "bar" 232 | 233 | menu "menu" 234 | visible if FOO || BAR 235 | 236 | config DEP_REM_CORNER_CASES 237 | prompt "prompt" 238 | depends on BAZ && QAZ 239 | 240 | endmenu 241 | 242 | # Only prompt, no type 243 | config PROMPT_ONLY 244 | prompt "prompt only" 245 | 246 | # {Symbol,Choice}.orig_* 247 | 248 | if BASE_DEP 249 | 250 | config BOOL_SYM_ORIG 251 | bool 252 | default D1 if DEP 253 | default D2 254 | select S1 255 | select S2 if DEP 256 | imply I1 257 | imply I1 258 | 259 | config BOOL_SYM_ORIG 260 | default D3 261 | select S3 262 | imply I3 if DEP 263 | 264 | config INT_SYM_ORIG 265 | int 266 | range 1 2 if DEP 267 | range 3 4 268 | 269 | config INT_SYM_ORIG 270 | range 5 6 if DEP 271 | 272 | choice CHOICE_ORIG 273 | bool "choice orig" 274 | default A 275 | default B if DEP 276 | 277 | config A 278 | bool 279 | 280 | config B 281 | bool 282 | 283 | endchoice 284 | 285 | choice CHOICE_ORIG 286 | default C if DEP 287 | 288 | config C 289 | bool 290 | 291 | endchoice 292 | 293 | endif 294 | -------------------------------------------------------------------------------- /tests/Kundef: -------------------------------------------------------------------------------- 1 | config DEF 2 | bool 3 | 4 | config BOOL 5 | bool "foo" if DEF || !UNDEF_1 6 | default UNDEF_2 7 | 8 | config INT 9 | int 10 | range UNDEF_2 8 11 | default 10 12 | range 5 15 13 | 14 | config HEX 15 | hex 16 | range 0x123 0X456 17 | default 0x200 18 | 19 | menu "menu" 20 | depends on UNDEF_1 21 | visible if UNDEF_3 22 | 23 | endmenu 24 | -------------------------------------------------------------------------------- /tests/Kuserfunctions: -------------------------------------------------------------------------------- 1 | add-zero = $(add) 2 | add-one = $(add,1) 3 | add-three = $(add,1,-1,2,1) 4 | 5 | one-zero = $(one) 6 | one-one = $(one,foo bar) 7 | one-two = $(one,foo bar,baz) 8 | 9 | one-or-more-zero = $(one-or-more) 10 | one-or-more-one = $(one-or-more,foo) 11 | one-or-more-three = $(one-or-more,foo,bar,baz) 12 | 13 | location-1 := $(location) 14 | location-2 := $(location) 15 | -------------------------------------------------------------------------------- /tests/Kvisibility: -------------------------------------------------------------------------------- 1 | config MODULES 2 | bool "MODULES" 3 | option modules 4 | 5 | # 6 | # Symbol visibility 7 | # 8 | 9 | config NO_PROMPT 10 | bool 11 | 12 | # Not rewritten, so MOD will have the value 'y' when running without modules 13 | config MOD 14 | def_tristate m 15 | 16 | config BOOL_N 17 | bool "bool n" if n 18 | 19 | config BOOL_M 20 | # Rewritten to m && MODULES 21 | bool "bool m" if m 22 | 23 | config BOOL_MOD 24 | bool "bool MOD" 25 | # Not rewritten 26 | depends on MOD 27 | 28 | config BOOL_Y 29 | bool "bool y" 30 | # Rewritten to m && MODULES 31 | depends on y || m 32 | 33 | config TRISTATE_N 34 | tristate "tristate n" if n 35 | 36 | config TRISTATE_M 37 | # Rewritten to m && MODULES 38 | tristate "tristate m" if m 39 | 40 | config TRISTATE_MOD 41 | tristate "tristate MOD" 42 | # Not rewritten 43 | depends on MOD 44 | 45 | config TRISTATE_Y 46 | bool "tristate y" 47 | # Rewritten to m && MODULES 48 | depends on y || m 49 | 50 | # Symbols nested in 'if' 51 | 52 | if n 53 | 54 | config BOOL_IF_N 55 | bool "bool if n" 56 | 57 | config TRISTATE_IF_N 58 | tristate "tristate if n" 59 | 60 | endif 61 | 62 | if m 63 | 64 | config BOOL_IF_M 65 | bool "bool if m" 66 | 67 | config TRISTATE_IF_M 68 | tristate "tristate if n" 69 | 70 | endif 71 | 72 | if y 73 | 74 | config BOOL_IF_Y 75 | bool "bool if y" 76 | 77 | config TRISTATE_IF_Y 78 | tristate "tristate if y" 79 | 80 | endif 81 | 82 | # Symbols nested in 'menu' 83 | 84 | menu "menu 1" 85 | depends on n 86 | 87 | config BOOL_MENU_N 88 | bool "bool menu n" 89 | 90 | config TRISTATE_MENU_N 91 | tristate "tristate menu n" 92 | 93 | endmenu 94 | 95 | menu "menu 2" 96 | depends on m 97 | 98 | config BOOL_MENU_M 99 | bool "bool menu m" 100 | 101 | config TRISTATE_MENU_M 102 | tristate "tristate menu n" 103 | 104 | endmenu 105 | 106 | menu "menu 3" 107 | depends on y 108 | 109 | config BOOL_MENU_Y 110 | bool "bool menu y" 111 | 112 | config TRISTATE_MENU_Y 113 | tristate "tristate menu y" 114 | 115 | endmenu 116 | 117 | # Symbols nested in choices 118 | 119 | choice C1 120 | tristate "choice n" if n 121 | 122 | config BOOL_CHOICE_N 123 | bool "bool choice n" 124 | 125 | config TRISTATE_CHOICE_N 126 | tristate "tristate choice n" 127 | 128 | endchoice 129 | 130 | choice C2 131 | tristate "choice m" if m 132 | 133 | config BOOL_CHOICE_M 134 | bool "bool choice m" 135 | 136 | config TRISTATE_CHOICE_M 137 | tristate "tristate choice n" 138 | 139 | endchoice 140 | 141 | choice C3 142 | tristate "choice y" if y 143 | 144 | config BOOL_CHOICE_Y 145 | bool "bool choice y" 146 | 147 | config TRISTATE_CHOICE_Y 148 | tristate "tristate choice y" 149 | 150 | endchoice 151 | 152 | # 153 | # Choice visibility 154 | # 155 | 156 | choice BOOL_CHOICE_N 157 | bool "bool choice n" if n 158 | endchoice 159 | 160 | choice BOOL_CHOICE_M 161 | bool "bool choice m" if m 162 | endchoice 163 | 164 | choice BOOL_CHOICE_Y 165 | bool "bool choice y" if y 166 | endchoice 167 | 168 | choice TRISTATE_CHOICE_N 169 | tristate "tristate choice n" if n 170 | endchoice 171 | 172 | choice TRISTATE_CHOICE_M 173 | tristate "tristate choice m" if m 174 | endchoice 175 | 176 | choice TRISTATE_CHOICE_Y 177 | tristate "tristate choice y" if y 178 | 179 | config K 180 | tristate "K" 181 | 182 | config L 183 | tristate "L" 184 | 185 | endchoice 186 | 187 | if m 188 | choice TRISTATE_CHOICE_IF_M_AND_Y 189 | tristate "tristate choice if m and y" if y 190 | 191 | config M 192 | bool "M" 193 | 194 | config N 195 | bool "N" 196 | 197 | endchoice 198 | endif 199 | 200 | menu "choice-containing menu" 201 | depends on n && y 202 | 203 | choice TRISTATE_CHOICE_MENU_N_AND_Y 204 | tristate "tristate choice if n and y" 205 | 206 | config O 207 | tristate "O" 208 | 209 | config P 210 | tristate "P" 211 | 212 | endchoice 213 | 214 | endmenu 215 | 216 | # 217 | # Menu visibility 218 | # 219 | 220 | menu "menu n" 221 | depends on n 222 | endmenu 223 | 224 | menu "menu m" 225 | depends on m 226 | endmenu 227 | 228 | menu "menu y" 229 | depends on y 230 | endmenu 231 | 232 | if n 233 | menu "menu if n" 234 | endmenu 235 | endif 236 | 237 | if m 238 | menu "menu if m" 239 | endmenu 240 | endif 241 | 242 | if y 243 | menu "menu if y" 244 | endmenu 245 | endif 246 | 247 | if m 248 | menu "menu if m and y" 249 | depends on y 250 | endmenu 251 | endif 252 | 253 | # 254 | # Comment visibility 255 | # 256 | 257 | comment "comment n" 258 | depends on n 259 | comment "comment m" 260 | depends on m 261 | comment "comment y" 262 | depends on y 263 | 264 | if n 265 | comment "comment if n" 266 | endif 267 | 268 | if m 269 | comment "comment if m" 270 | endif 271 | 272 | if y 273 | comment "comment if y" 274 | endif 275 | 276 | if "y" 277 | 278 | menu "menu with comment" 279 | depends on m 280 | 281 | comment "double-nested m comment" 282 | depends on y 283 | 284 | endmenu 285 | 286 | endif 287 | 288 | # Used to verify that string/int/hex symbols with m visibility accept a user 289 | # value 290 | 291 | if m 292 | 293 | config STRING_m 294 | string "string" 295 | 296 | config INT_m 297 | int "int" 298 | 299 | config HEX_m 300 | hex "hex" 301 | 302 | endif 303 | 304 | # Menu 'visible if' visibility 305 | 306 | menu "n-visible menu" 307 | visible if n 308 | 309 | config VISIBLE_IF_N 310 | tristate "visible if n" 311 | 312 | endmenu 313 | 314 | menu "m-visible menu" 315 | visible if m 316 | 317 | config VISIBLE_IF_M 318 | tristate "visible if m" 319 | 320 | endmenu 321 | 322 | menu "y-visible menu" 323 | visible if y 324 | 325 | config VISIBLE_IF_Y 326 | tristate "visible if m" 327 | 328 | endmenu 329 | 330 | menu "m-visible menu 2" 331 | visible if y || n 332 | visible if m && y 333 | visible if y 334 | 335 | if y 336 | 337 | config VISIBLE_IF_M_2 338 | tristate "visible if m 2" 339 | 340 | endif 341 | 342 | endmenu 343 | -------------------------------------------------------------------------------- /tests/config_indented: -------------------------------------------------------------------------------- 1 | # Indented assignments should be ignored to be compatible with the C 2 | # implementation 3 | CONFIG_IGNOREME=n 4 | -------------------------------------------------------------------------------- /tests/config_set_bool: -------------------------------------------------------------------------------- 1 | CONFIG_BOOL=y 2 | -------------------------------------------------------------------------------- /tests/config_set_string: -------------------------------------------------------------------------------- 1 | CONFIG_STRING="foo bar" 2 | -------------------------------------------------------------------------------- /tests/defconfig_1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ulfalizer/Kconfiglib/061e71f7d78cb057762d88de088055361863deff/tests/defconfig_1 -------------------------------------------------------------------------------- /tests/defconfig_2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ulfalizer/Kconfiglib/061e71f7d78cb057762d88de088055361863deff/tests/defconfig_2 -------------------------------------------------------------------------------- /tests/empty: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ulfalizer/Kconfiglib/061e71f7d78cb057762d88de088055361863deff/tests/empty -------------------------------------------------------------------------------- /tests/kconfigfunctions.py: -------------------------------------------------------------------------------- 1 | def add(kconf, name, *args): 2 | return str(sum(map(int, args))) 3 | 4 | 5 | def one(kconf, name, s): 6 | return name + 2*s 7 | 8 | 9 | def one_or_more(kconf, name, arg, *args): 10 | return arg + " + " + ",".join(args) 11 | 12 | 13 | def location(kconf, name): 14 | return "{}:{}".format(kconf.filename, kconf.linenr) 15 | 16 | 17 | functions = { 18 | "add": (add, 0, None), 19 | "one": (one, 1, 1), 20 | "one-or-more": (one_or_more, 1, None), 21 | "location": (location, 0, 0), 22 | } 23 | -------------------------------------------------------------------------------- /tests/reltest: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Runs the test suite and all examples scripts with Python 2 and Python 3, 4 | # bailing immediately if anything fails. For the examples that aren't tested in 5 | # the test suite, we just confirm that they at least run. 6 | # 7 | # Should be run from the kernel root with $ Kconfiglib/tests/reltest 8 | 9 | test_script() { 10 | echo -e "\n================= $1 with $py =================\n" 11 | if (($# == 1)); then 12 | make scriptconfig PYTHONCMD=$py SCRIPT=$1 13 | else 14 | make scriptconfig PYTHONCMD=$py SCRIPT=$1 SCRIPT_ARG="$2" 15 | fi 16 | 17 | if (($?)); then 18 | echo "$1 failed to run with $py" 19 | exit 1 20 | fi 21 | } 22 | 23 | for py in python2 python3; do 24 | echo -e "\n================= Test suite with $py =================\n" 25 | 26 | if ! $py Kconfiglib/testsuite.py; then 27 | echo "test suite failed for $py" 28 | exit 1 29 | fi 30 | 31 | # Check that the example scripts that aren't tested by the test suite run 32 | # at least 33 | 34 | test_script Kconfiglib/examples/defconfig_oldconfig.py 35 | test_script Kconfiglib/examples/eval_expr.py MODULES 36 | test_script Kconfiglib/examples/find_symbol.py X86 37 | test_script Kconfiglib/examples/help_grep.py general 38 | test_script Kconfiglib/examples/print_sym_info.py MODULES 39 | test_script Kconfiglib/examples/print_tree.py 40 | 41 | $py Kconfiglib/examples/menuconfig_example.py Kconfiglib/examples/Kmenuconfig <