cpreprocessordevice-tree

Final State of DTS After Preprocessing


In short, what is the final textual state of a valid DTS file after it has been run through the C preprocessor? Exactly what should be left behind from #include directives? How much of this is dtc supposed to tolerate? Did the Linux headers have to be specially laid out to support inclusion in a DTS file?


For fun and profit, I am adding device tree support to a FreeRTOS project. In doing so, I need to add build support to actually generate and embed my DTB into the final binary. The first step is to run the preprocessor on the DTS to convert C definitions. This preprocessed DTS is then fed to dtc to create the final DTB.

I have all of the build integration and such working but I am getting tripped up by the preprocess step. I have seen numerous posts online which all are a variation on the arguments specified here; my specific incantation (I am using CMake currently) is:

"${CMAKE_C_COMPILER}" "-D$<JOIN:$<TARGET_PROPERTY:${COMPONENT_LIB},COMPILE_DEFINITIONS>,$<SEMICOLON>-D>"
                      "-I$<JOIN:$<TARGET_PROPERTY:${COMPONENT_LIB},INCLUDE_DIRECTORIES>,$<SEMICOLON>-I>"
                       -E -P --undef __ASSEMBLER__ -x assembler-with-cpp -o "${CURRENT_DTS_PREPROCESS}" "${CURRENT_DTS}"

This command completes successfully but the subsequent dtc step fails to parse the preprocessed DTS with syntax errors. If I examine these errors, they are all on C declarations that would survive the proprocessor. For example, here are the first couple of lines of the preprocessed output:

/dts-v1/;


typedef signed char __int8_t;
typedef unsigned char __uint8_t;
typedef short int __int16_t;
typedef short unsigned int __uint16_t;
typedef int __int32_t;
typedef unsigned int __uint32_t;
typedef long long int __int64_t;
...

Presumably the first include file to be considered is stdint.h or similar, hence the definitions for all of the fixed-width types first. The first syntax error reported by dtc is /path/to/dts.preprocess:4.1-8 syntax error which exactly corresponds to the first typedef token (with trailing space).

So, should the device tree compiler be tolerant of this or am I missing something in my incantation to elide all C definitions that aren't #define substitutions? Or is there something else at work here?


Solution

  • Per discussion on the Linux Kernel Mailing List as well as @JohnBollinger's and @sawdust's comment, it looks like the Linux headers had to be specifically laid out to support inclusion into a device tree. Specifically, they were intentionally set up to not contain C directives which are not valid DTS syntax. Bummer.

    Near as I can tell, the only way to do this without duplicating / reworking headers would be ANOTHER process step after the C preprocessor but before dtc invocation to strip out the leftover C gunk. This is left as an exercise for the reader.