[PATCH 4/6] dtoc: Only generate the required files

Simon Glass sjg at chromium.org
Wed Mar 24 08:07:12 CET 2021

At present all possible files are generated, even if some of them just
have a header and an empty body. It is better to generate only the files
that are needed, so that the two types of build (based on the setting of
OF_PLATDATA_INST) can be mutually exclusive.

This is intended to fix a strange problem sometimes found with CI:

   Building current source for 1 boards (1 thread, 40 jobs per thread)
      sandbox:  +   sandbox_spl
   +drivers/built-in.o: In function `dm_setup_inst':
   +drivers/core/root.c:135: undefined reference to
   +dts/dt-uclass.o:(.u_boot_list_2_uclass_2_serial+0x10): undefined
   reference to `_u_boot_list_2_udevice_2_serial'

This likely happens when switching from !OF_PLATDATA_INST to
OF_PLATDATA_INST since running 'make xxx_defconfig" does not currently
cause any change in which files are generated. With !OF_PLATDATA_INST
the dt-device.c file has no declarations and this is assumed to be the
starting state. The error above seems to indicate that, after changing
to OF_PLATDATA_INST, the dt-uclass.c file is regenerated but the
dt-device.c files is not. This does not seem possible from the relevant
Makefile.spl rule:

   u-boot-spl-platdata := $(obj)/dts/dt-plat.o $(obj)/dts/dt-uclass.o

   cmd_dtoc = $(DTOC_ARGS) -c $(obj)/dts -C include/generated all

   include/generated/dt-structs-gen.h $(u-boot-spl-platdata_c) &: \
	@[ -d $(obj)/dts ] || mkdir -p $(obj)/dts
	$(call if_changed,dtoc)

It seems that this cannot regenerate dt-uclass.c without dt-device.c since
'dtoc all' is used. So here the trail ends for now.

In any case it seems better to generate files that are uses and not bother
with those that serve no purpose. So update dtoc to do this automatically.

Signed-off-by: Simon Glass <sjg at chromium.org>

 tools/dtoc/dtb_platdata.py | 23 +++++++++++++++++++----
 tools/dtoc/test_dtoc.py    |  2 +-
 2 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/tools/dtoc/dtb_platdata.py b/tools/dtoc/dtb_platdata.py
index b5c449ebb47..c9c657cb9a9 100644
--- a/tools/dtoc/dtb_platdata.py
+++ b/tools/dtoc/dtb_platdata.py
@@ -1128,7 +1128,7 @@ class DtbPlatdata():
 # Types of output file we understand
 # key: Command used to generate this file
 # value: OutputFile for this command
         OutputFile(Ftype.HEADER, 'dt-decl.h', DtbPlatdata.generate_decl,
                    'Declares externs for all device/uclass instances'),
@@ -1136,9 +1136,17 @@ OUTPUT_FILES = {
         OutputFile(Ftype.HEADER, 'dt-structs-gen.h',
                    'Defines the structs used to hold devicetree data'),
+    }
+# File generated without instantiate
         OutputFile(Ftype.SOURCE, 'dt-plat.c', DtbPlatdata.generate_plat,
                    'Declares the U_BOOT_DRIVER() records and platform data'),
+    }
+# File generated with instantiate
         OutputFile(Ftype.SOURCE, 'dt-device.c', DtbPlatdata.generate_device,
                    'Declares the DM_DEVICE_INST() records'),
@@ -1204,14 +1212,21 @@ def run_steps(args, dtb_file, include_disabled, output, output_dirs, phase,
+    # Figure out what output files we plan to generate
+    output_files = OUTPUT_FILES_COMMON
+    if instantiate:
+        output_files.update(OUTPUT_FILES_INST)
+    else:
+        output_files.update(OUTPUT_FILES_NOINST)
     cmds = args[0].split(',')
     if 'all' in cmds:
-        cmds = sorted(OUTPUT_FILES.keys())
+        cmds = sorted(output_files.keys())
     for cmd in cmds:
-        outfile = OUTPUT_FILES.get(cmd)
+        outfile = output_files.get(cmd)
         if not outfile:
             raise ValueError("Unknown command '%s': (use: %s)" %
-                             (cmd, ', '.join(sorted(OUTPUT_FILES.keys()))))
+                             (cmd, ', '.join(sorted(output_files.keys()))))
                           outfile.fname if output_dirs else output)
diff --git a/tools/dtoc/test_dtoc.py b/tools/dtoc/test_dtoc.py
index 1912a8723f2..e9512834574 100755
--- a/tools/dtoc/test_dtoc.py
+++ b/tools/dtoc/test_dtoc.py
@@ -1554,7 +1554,7 @@ U_BOOT_DRVINFO(spl_test2) = {
         with self.assertRaises(ValueError) as exc:
             self.run_test(['invalid-cmd'], dtb_file, output)
-            "Unknown command 'invalid-cmd': (use: decl, device, platdata, struct, uclass)",
+            "Unknown command 'invalid-cmd': (use: decl, platdata, struct)",
     def test_output_conflict(self):

More information about the U-Boot mailing list