xref: /optee_os/scripts/kconfig/kconfiglib/genconfig.py (revision c689edbb2550c76ae81dcecab717d82a564b2d7b)
1#!/usr/bin/env python3
2
3# Copyright (c) 2018-2019, Ulf Magnusson
4# SPDX-License-Identifier: ISC
5
6"""
7Generates a header file with #defines from the configuration, matching the
8format of include/generated/autoconf.h in the Linux kernel.
9
10Optionally, also writes the configuration output as a .config file. See
11--config-out.
12
13The --sync-deps, --file-list, and --env-list options generate information that
14can be used to avoid needless rebuilds/reconfigurations.
15
16Before writing a header or configuration file, Kconfiglib compares the old
17contents of the file against the new contents. If there's no change, the write
18is skipped. This avoids updating file metadata like the modification time, and
19might save work depending on your build setup.
20
21By default, the configuration is generated from '.config'. A different
22configuration file can be passed in the KCONFIG_CONFIG environment variable.
23
24A custom header string can be inserted at the beginning of generated
25configuration and header files by setting the KCONFIG_CONFIG_HEADER and
26KCONFIG_AUTOHEADER_HEADER environment variables, respectively (this also works
27for other scripts). The string is not automatically made a comment (this is by
28design, to allow anything to be added), and no trailing newline is added, so
29add '/* */', '#', and newlines as appropriate.
30
31See https://www.gnu.org/software/make/manual/make.html#Multi_002dLine for a
32handy way to define multi-line variables in makefiles, for use with custom
33headers. Remember to export the variable to the environment.
34"""
35import argparse
36import os
37import sys
38
39import kconfiglib
40
41
42DEFAULT_SYNC_DEPS_PATH = "deps/"
43
44
45def 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="""
54Path to write the generated header file to. If not specified, the path in the
55environment variable KCONFIG_AUTOHEADER is used if it is set, and 'config.h'
56otherwise.
57""")
58
59    parser.add_argument(
60        "--config-out",
61        metavar="CONFIG_FILE",
62        help="""
63Write the configuration to CONFIG_FILE. This is useful if you include .config
64files in Makefiles, as the generated configuration file will be a full .config
65file even if .config is outdated. The generated configuration matches what
66olddefconfig would produce. If you use sync-deps, you can include
67deps/auto.conf instead. --config-out is meant for cases where incremental build
68information 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="""
77Enable generation of symbol dependency information for incremental builds,
78optionally specifying the output directory (default: {}). See the docstring of
79Kconfig.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="""
86Write a list of all Kconfig files to OUTPUT_FILE, with one file per line. The
87paths are relative to $srctree (or to the current directory if $srctree is
88unset). Files appear in the order they're 'source'd.
89""")
90
91    parser.add_argument(
92        "--env-list",
93        metavar="OUTPUT_FILE",
94        help="""
95Write a list of all environment variables referenced in Kconfig files to
96OUTPUT_FILE, with one variable per line. Each line has the format NAME=VALUE.
97Only environment variables referenced with the preprocessor $(VAR) syntax are
98included, and not variables referenced with the older $VAR syntax (which is
99only 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
144def _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
153if __name__ == "__main__":
154    main()
155