Wiki:help/howtos/development/menuconfig

Menükonfiguration pflegen

Einer der ersten Schritte jedes Freetz-Benutzers ist die Auswahl der gewünschten Firmware (FW)-Konfiguration mit make menuconfig. Die Menükonfiguration (MK) ist mithin die primäre Benutzerschnittstelle neben der Linux-Shell für alle Nicht-Entwickler. Fehler und Unstimmigkeiten, welche dort auftauchen, können bestenfalls zu Verwirrung und Fragen im IPPF Freetz-Forum führen, aber auch zu seltsamen Warnungen auf der Konsole nach dem Speichern der Konfiguration, zu fehlenden oder überflüssigen FW-Bestandteilen oder schlimmstenfalls zu Freetz-Boxen, die nicht mehr booten oder in Reboot-Schleifen festhängen. In jedem Fall entsteht Support-Aufwand. Am billigsten sind, gemäß dem agilen Mantra "fail early", jedoch Fehler, die frühestmöglich bemerkt werden oder am besten gar nicht erst entstehen. Die Pflege der Menükonfiguration ist ein wichtiger Qualitäts-Baustein unseres Projektes.

Einstieg

Pflichtlektüre jedes Entwicklers, bevor er zum ersten Mal die MK anpaßt, sollte die Beschreibung der Kconfig-Sprache sein. Dort werden Syntax-Features und deren Gebrauch grundlegend erklärt. Die Beschreibung entstammt der Dokumentation des Linux-Kernels, welchem wir (und auch andere quelloffene Projekte) diese Art der MK und die dazu notwendigen Werkzeuge entlehnt haben.

Die wichtigste Dateien und Make-Targets, mit welchen wir es im Folgenden zu tun haben werden, sind

  • Config.in
    • enthält das Hauptgerüst der MK
    • ist in der Kconfig-Sprache geschrieben
    • inkludiert hierarchisch (Baumstruktur) mittels source-Direktive weitere MK-Definitionen, welche ebenfalls Namen wie Config.in, externals.in o.ä. tragen
    • wird zukünftig (Trunk-Merge steht kurz bevor) als Ganzes, also mit allen Includes, gepuffert in Config.in.cache, um Ladezeiten beim Aufruf von make menuconfig zu verringern.
  • .config
    • enthält die vom Benutzer erstellte FW-Konfiguration als maßgebliche Vorausstzung für folgende Builds
    • ist als Kopie in der FW unter /etc/.config enthalten, sofern das nicht in der MK vor dem Build deselektiert wird
    • ist eines der primären Debugging-Werkzeuge, wenn Benutzer Fehler mit einer bestimmten Konfiguration melden
    • kann, sollte aber nicht manuell editiert werden
  • tools/config/mconf
    • ist das Binary, welches von make menuconfig aufgerufen wird, um die MK anzuzeigen und zu speichern
    • wird mittels make tools bzw. make kconfig automatisch gebaut, sobald es benötigt wird
    • hat auch ein Make-Target menuconfig-single, welches die KM als Baumstruktur ohne Unterseiten darstellt (manchmal nett, wenn man die Gesamtstruktur sehen bzw. bearbeiten möchte)
  • tools/config/conf
    • ist die Kommandozeilenversion von mconf
    • hat mehr Features
    • wird ebenfalls mittels make tools bzw. make kconfig automatisch gebaut, sobald es benötigt wird
    • wird von den Make-Targets config, oldconfig, oldnoconfig, defconfig, allnoconfig, allyesconfig, randconfig, listnewconfig, config-clean-deps und config-clean-deps-keep-busybox benutzt
    • zeigt folgende Hilfe an, wenn ohne Parameter aufgerufen (klappt Stand 15.10.2011 im Trunk, nicht in älteren Stable-Versionen, also frühestens ab Freetz 1.2):
      Usage: tools/config/conf [option] <kconfig-file>
      [option] is _one_ of the following:
        --listnewconfig         List new options
        --oldaskconfig          Start a new configuration using a line-oriented program
        --oldconfig             Update a configuration using a provided .config as base
        --silentoldconfig       Same as oldconfig, but quietly, additionally update deps
        --oldnoconfig           Same as silentoldconfig but set new symbols to no
        --defconfig <file>      New config with default defined in <file>
        --savedefconfig <file>  Save the minimal current configuration to <file>
        --allnoconfig           New config where all options are answered with no
        --allyesconfig          New config where all options are answered with yes
        --allmodconfig          New config where all options are answered with mod
        --alldefconfig          New config with all symbols set to default
        --randconfig            New config with random answer to all options
      

Beispiel-Konfiguration für ein neues Paket

TODO

TODO

Siehe vorerst #1532, insbes. Kommentare Nr.

  • 10: Erklärung einer Warnung mit Vorschlägen zur Problembehebung

    Diese unmet dependencies behebt am besten jeder so, wie der gerade drauf stößt. Es sind ja nur Warnings, aber die sind auch wichtig, damit wir Unsauberkeiten aus den Config.in heraus bekommen. Das ist also gut für die Projekthygiene. Ich gebe mal ein Beispiel:

    warning: (FREETZ_PACKAGE_AUTOFS_NFS && FREETZ_PACKAGE_NFSROOT)
        selects FREETZ_MODULE_nfs which has unmet direct dependencies
        (FREETZ_KERNEL_VERSION_2_6_13_1 || FREETZ_KERNEL_VERSION_2_6_28 ||
         FREETZ_KERNEL_VERSION_2_6_32)
    

    Aha, hier hat also jemand (ich) NFS-Root ausgewählt. Klar, daß dazu auch das NFS-Kernelmodul ausgewählt werden muß. Jetzt hat dieser Jemand aber bspw. eine 7270_v1 mit Kernel 2.6.19.2. Das Problem liegt auf der Hand: Entweder sollte beim NFS-Modul dieser Kernel mit in die Dependencies-Liste, oder für diesen Kernel sollten alle NFS-relevanten Sachen deaktiviert werden. Alles andere ist ein Widerspruch, und der wird moniert von Kconfig. Was in diesem Fall sachlich zutreffend ist, weiß ich momentan nicht, dafür war ich zu lange zu weit weg von der Entwicklung.

  • 24: Liste aktueller Warnungen mit Erläuterungen zu Ursachen und möglichen Lösungen
  • 31: konkretes Beispiel einer von Alexander Kriegisch eingecheckten Problembehebung

    Ich versuche es einfach statt in Prosa mal schematisch: :-)

    FREETZ_PACKAGE_DAVFS2
        select FREETZ_REMOVE_WEBDAV if FREETZ_HAS_AVM_WEBDAV
    
    FREETZ_REMOVE_WEBDAV
        depends on FREETZ_HAS_AVM_WEBDAV
    
    FREETZ_HAS_AVM_WEBDAV
        depends on FREETZ_TYPE_FON_WLAN_7240 || ...
    

    Das sieht mir sauber genug aus, obwohl das "if FREETZ_HAS_AVM_WEBDAV" - da gebe ich Dir recht - in Deinem Sinne doppelt ist. Aber es sagt dafür genauer, was Du wirklich tun willst (man kann die Konfigurationsanweisung diesmal wirklich wie Prosa lesen): Wähle den Remove-Patch aus, falls es überhaupt etwas zu entfernen gibt. Ich denke, das macht es hinreichend klar und dokumentiert nochmals, was gewollt ist. Zudem vermeidet es die Warnung nach dem Speichern der Konfiguration. Ohne das If würde die Warnung erscheinen.

  • 54: verallgemeintertes "Kochrezept" zur Problembehebung bei Remove-Patches

    Ich weise nochmals auf meinen Kommentar #31 hin, aus dem man im Grunde sehr schön ablesen kann, wie einfach, elegant und lesbar man viele Situationen beheben kann:

    FREETZ_PACKAGE_FOO
        select FREETZ_REMOVE_MY_FEATURE if FREETZ_HAS_AVM_MY_FEATURE
    
    FREETZ_REMOVE_MY_FEATURE
        depends on FREETZ_HAS_AVM_MY_FEATURE
    
    FREETZ_HAS_AVM_MY_FEATURE
        depends on FREETZ_TYPE_A || FREETZ_TYPE_B || ...
    

    Kochrezept für Remove-Patches (RP):

    • Automatische RP-Auswahl absichern durch if FREETZ_HAS_AVM_MY_FEATURE
    • RP-Sichtbarkeit abhängig machen durch depends on FREETZ_HAS_AVM_MY_FEATURE
    • Durch RP entfernbares Feature abhängig machen von Hardware oder Firmware usw. durch depends on FREETZ_TYPE_A
  • 55: weitere Erläuterungen zur Umsetzung des Kochrezepts

    Replying to oliver:

    Wo ist der Sinn darin eine dependency herauszunehmen, die (bis auf wenige Fälle) richtig ist?

    Jetzt habe ich mir den ersten Patch doch schnell mal angeschaut. Es ist weder korrekt, sie so drin zu lassen, wenn sie auch nur in wenigen Fällen falsch ist, noch, sie ersatzlos zu streichen, wenn unsinnige Optionen dafür in neuen, falschen Fällen angezeigt werden. Was hingegen Sinn (und etwas Mühe) machen würde, wäre, mein Kochrezept anzuwenden und neue Variablen FREETZ_HAS_AVM_AURA_USB, FREETZ_HAS_AVM_PRINTSERV und FREETZ_HAS_AVM_RUNCLOCK anzulegen. Die könnte FREETZ_HAS_USB_HOST ja von mir aus in den Fällen, wo es keine gegenteiligen Erkenntnisse gibt, automatisch auswählen. Sobald aber auch nur eine einzige Ausnahme bekannt ist, ist eine Box-Liste beim jeweiligen FREETZ_HAS_AVM_* zu hinterlegen. Die Remove-Patches sollten immer von FREETZ_HAS_AVM_* abhängen, nie von einem billigen Ersatz der nur fast immer funktioniert.

    Das ist keine Kritik i.S.v. "das hättest Du aber vorher wissen sollen", denn die Erkenntnisse sind ja relativ neu und m.E. ein Segen des neuen Kconfig. Ich will durch meine Hinweise den anderen Entwicklern Hilfe zur Selbsthilfe geben.

    Ergänzung: Es ist auch sowas vorstellbar:

    FREETZ_HAS_AVM_MY_FEATURE
        depends on FREETZ_HAS_USB_HOST && !(FREETZ_TYPE_A || FREETZ_TYPE_B)
    

    So hält man die Boxen-Liste klein, indem man einfach klar sagt, was Sache ist. Es ist wieder fast wie Prosa lesbar: "Zeig das AVM-Feature X an, wenn die Box einen USB-Host hat, außer in den Ausnahmefällen A und B."

Erklärung und Anwendung der erweiterten MK-Targets

TODO

Syntax-Fehler in MK-Dateien finden

Wir sehen einen Fehler wie diesen:

$ make menuconfig

Config.in.cache:4951: syntax error
Config.in.cache:4950: unknown option "xconfig"
Config.in.cache:4951:warning: prompt redefined
make: *** [menuconfig] Error 1

Gemäß Beschreibung in r8466 gibt es zwei Wege, bei einem von make menuconfig angezeigten Syntax-Fehler schnell die fehlerhafte Stelle zu finden:

  1. In Config.cache.in direkt zu der Fehlerzeile 4950 springen, die auf der Konsole angezeigt wurde. Von dort aus rückwärts(!) suchen nach INCLUDE_BEGIN - voilà, dort steht der Dateiname, wo die fehlerhafte MK zu finden ist.
  2. make menuconfig-nocache aufrufen und die problematische Datei (make/davfs2/Config.in) direkt von der Konsole ablesen:
    $ make menuconfig-nocache
    
    make/davfs2/Config.in:2: syntax error
    make/Config.in:84: missing end statement for this entry
    Config.in:851: missing end statement for this entry
    make/davfs2/Config.in:1: invalid statement
    make/davfs2/Config.in:2: unexpected option "bool"
    make/davfs2/Config.in:3: unexpected option "select"
    make/davfs2/Config.in:4: unexpected option "select"
    make/davfs2/Config.in:5: unexpected option "select"
    make/davfs2/Config.in:6: unexpected option "select"
    make/davfs2/Config.in:7: unexpected option "select"
    make/davfs2/Config.in:8: unexpected option "select"
    make/davfs2/Config.in:9: unexpected option "default"
    make/davfs2/Config.in:10: invalid statement
    make/davfs2/Config.in:11: unknown statement "davfs"
    make/davfs2/Config.in:12: unknown statement "WebDAV"
    make/davfs2/Config.in:13: unknown statement "HTTP"
    make/davfs2/Config.in:14: unknown statement "resources"
    make/Config.in:199: unexpected end statement
    Config.in:862: unexpected end statement
    make: *** [menuconfig-nocache] Error 1
    

Syntax-Hervorhebung für MK-Dateien

Gemäß Patch 1 habe ich (Alexander Kriegisch, kriegaex) zunächst einen sog. Lexer für Pygments gebaut (siehe auch Pygments-Doku), welcher es ermöglicht, MK-Dateien mit Syntax-Hervorhebung zu versehen. Pygments wird von Trac, also dem System, auf welchem unser Wiki und der Repository Browser basieren, automatisch benutzt, sofern es installiert ist.

Trac erkennt den MIME-Typ einer Datei aber nur aufgrund der Endung (also z.B. .py, .sh, .pl, .c, .h) oder aufgrund Infos wie Shebang oder Vi-/Emacs-Header, und das ist ein Problem bei MK-Dateien, da es keine standardisierte Dateiendung im Allgemeinen und auch nicht bei uns im Projekt gibt. Unsere einzige Chance ist es, den Wildwuchs an Dateinamen (z.B. Config.in, external.in, standard-modules.in, external.in.libs) so im Zaum zu halten, daß man mit Regex Matching die entsprechenden Dateien identifizieren kann. Das ist Stand heute möglich, allerdings beherrscht Trac von Haus aus kein Regex Matching, weswegen Patch 2 notwendig wird. (Anm.: Bevor es Patch 2 gab, war es notwendig, in SVN die Eigenschaft svn:mime-type für jede MK-Datei manuell zu setzen, was inzwischen zum Glück obsolet ist, aber auch nicht schaden würde.)

Auf unserem Webserver sind beide Patches nebst der notwendigen Konfiguration in trac.ini aktiv, so daß MK-Dateien aus dem SVN-Repository automatisch mit Syntax-Hervorhebung versehen werden.

Noch ein kleiner Tip: Wie man Syntax Highlighting im Trac-Wiki direkt in Code-Blocks einsetzt, sieht man hier direkt im Artikel für MK- und Shell-Code: Entweder man erwähnt am Anfang des Code-Blocks mit führendem Shebang den MIME-Typ (text/x-kconfig, übrigens selbst erfunden und kein allgemeiner Standard) oder das in trac.ini konfigurierte Schlüsselwort kconfig, also in etwa so:

{{{
#!text/x-kconfig
... MK-Code ...
}}}

Oder so:

{{{
#!kconfig
... MK-Code ...
}}}