1#!/usr/bin/env python
2
3# SPDX-License-Identifier: ISC
4# Copyright (c) 2018, Ulf Magnusson
5
6# Generates a C header from the configuration, matching the format of
7# include/generated/autoconf.h in the kernel.
8#
9# Optionally generates a directory structure with one file per symbol that can
10# be used to implement incremental builds. See the docstring for
11# Kconfig.sync_deps() in Kconfiglib.
12#
13# Usage (see argument help texts for more information):
14#
15#   genconfig.py [-h] [--header-path HEADER_FILE]
16#                [--sync-deps [OUTPUT_DIR]] [--config-out CONFIG_FILE]
17#                [KCONFIG_FILENAME]
18
19import argparse
20
21import kconfiglib
22
23DESCRIPTION = """
24Generates a header file with defines from the configuration. Optionally
25creates/updates a directory with incremental build information as well (see the
26docstring for the Kconfig.sync_deps() function in Kconfiglib). The .config file
27to generate the configuration from can be specified by setting the
28KCONFIG_CONFIG environment variable.
29"""
30
31DEFAULT_HEADER_PATH = "config.h"
32DEFAULT_SYNC_DEPS_PATH = "deps/"
33
34def main():
35    parser = argparse.ArgumentParser(description=DESCRIPTION)
36
37    parser.add_argument(
38        "--header-path",
39        metavar="HEADER_FILE",
40        default=DEFAULT_HEADER_PATH,
41        help="Path for the generated header file (default: {})"
42             .format(DEFAULT_HEADER_PATH))
43
44    parser.add_argument(
45        "--sync-deps",
46        dest="sync_deps_path",
47        metavar="OUTPUT_DIR",
48        nargs="?",
49        const=DEFAULT_SYNC_DEPS_PATH,
50        help="Enable generation of build dependency information for "
51             "incremental builds, optionally specifying the output path "
52             "(default: {})".format(DEFAULT_SYNC_DEPS_PATH))
53
54    parser.add_argument(
55        "--config-out",
56        dest="config_path",
57        metavar="CONFIG_FILE",
58        help="Write the configuration to the specified filename. "
59             "This is useful if you include .config files in Makefiles, as "
60             "the generated configuration file will be a full .config file "
61             "even if .config is outdated. The generated configuration "
62             "matches what olddefconfig would produce. If you use "
63             "--sync-deps, you can include deps/auto.conf instead. "
64             "--config-out is meant for cases where incremental build "
65             "information isn't needed.")
66
67    parser.add_argument(
68        "kconfig_filename",
69        metavar="KCONFIG_FILENAME",
70        nargs="?",
71        default="Kconfig",
72        help="Top-level Kconfig file (default: Kconfig)")
73
74    args = parser.parse_args()
75
76
77    kconf = kconfiglib.Kconfig(args.kconfig_filename)
78    kconf.load_config(verbose=False)
79
80    kconf.write_autoconf(args.header_path)
81
82    if args.sync_deps_path is not None:
83        kconf.sync_deps(args.sync_deps_path)
84
85    if args.config_path is not None:
86        kconf.write_config(args.config_path, save_old=False)
87
88if __name__ == "__main__":
89    main()
90