Browse Source

cmake: modules: Add zephyr_dt_import

Extract the part of `dts.cmake` that invokes `gen_dts_cmake.py`, then
generalize it into a CMake extension, which can be reused by sysbuild.

The Python script itself is also updated, so that the generated CMake
file can accept an input variable DEVICETREE_TARGET, which comes from
the `zephyr_dt_import(TARGET ...)` argument.

Signed-off-by: Grzegorz Swiderski <grzegorz.swiderski@nordicsemi.no>
pull/90333/head
Grzegorz Swiderski 2 months ago committed by Benjamin Cabé
parent
commit
468db18389
  1. 34
      cmake/modules/dts.cmake
  2. 39
      cmake/modules/extensions.cmake
  3. 20
      scripts/dts/gen_dts_cmake.py

34
cmake/modules/dts.cmake

@ -122,12 +122,6 @@ set(GEN_DRIVER_KCONFIG_SCRIPT ${DT_SCRIPTS}/gen_driver_kconfig_dts.py)
# Generated Kconfig symbols go here. # Generated Kconfig symbols go here.
set(DTS_KCONFIG ${KCONFIG_BINARY_DIR}/Kconfig.dts) set(DTS_KCONFIG ${KCONFIG_BINARY_DIR}/Kconfig.dts)
# This generates DT information needed by the CMake APIs.
set(GEN_DTS_CMAKE_SCRIPT ${DT_SCRIPTS}/gen_dts_cmake.py)
# The generated information itself, which we include() after
# creating it.
set(DTS_CMAKE ${PROJECT_BINARY_DIR}/dts.cmake)
# The location of a file containing known vendor prefixes, relative to # The location of a file containing known vendor prefixes, relative to
# each element of DTS_ROOT. Users can define their own in their own # each element of DTS_ROOT. Users can define their own in their own
# modules. # modules.
@ -283,7 +277,6 @@ set_property(DIRECTORY APPEND PROPERTY
${GEN_EDT_SCRIPT} ${GEN_EDT_SCRIPT}
${GEN_DEFINES_SCRIPT} ${GEN_DEFINES_SCRIPT}
${GEN_DRIVER_KCONFIG_SCRIPT} ${GEN_DRIVER_KCONFIG_SCRIPT}
${GEN_DTS_CMAKE_SCRIPT}
) )
# #
@ -356,31 +349,12 @@ if(NOT "${ret}" STREQUAL "0")
endif() endif()
# #
# Run GEN_DTS_CMAKE_SCRIPT. # Import devicetree contents into CMake.
# # This enables the CMake dt_* API.
# A temporary file is copied to the original file if it differs. This prevents issue such as a
# cycle when sysbuild is used of configuring and building multiple times due to the dts.cmake file
# of images having a newer modification time than the sysbuild build.ninja file, despite the
# output having not changed
# #
set(dts_cmake_tmp ${DTS_CMAKE}.new)
execute_process( add_custom_target(devicetree_target)
COMMAND ${PYTHON_EXECUTABLE} ${GEN_DTS_CMAKE_SCRIPT} zephyr_dt_import(EDT_PICKLE_FILE ${EDT_PICKLE} TARGET devicetree_target)
--edt-pickle ${EDT_PICKLE}
--cmake-out ${dts_cmake_tmp}
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
RESULT_VARIABLE ret
)
if(NOT "${ret}" STREQUAL "0")
message(FATAL_ERROR "gen_dts_cmake.py failed with return code: ${ret}")
else()
zephyr_file_copy(${dts_cmake_tmp} ${DTS_CMAKE} ONLY_IF_DIFFERENT)
file(REMOVE ${dts_cmake_tmp})
set(dts_cmake_tmp)
message(STATUS "Including generated dts.cmake file: ${DTS_CMAKE}")
include(${DTS_CMAKE})
endif()
# #
# Run dtc if it was found. # Run dtc if it was found.

39
cmake/modules/extensions.cmake

@ -4625,6 +4625,45 @@ function(zephyr_dt_preprocess)
endif() endif()
endfunction() endfunction()
# Usage:
# zephyr_dt_import(EDT_PICKLE_FILE <file> TARGET <target>)
#
# Parse devicetree information and make it available to CMake, so that
# it can be accessed by the dt_* CMake extensions from section 4.1.
#
# This requires running a Python script, which can take the output of
# edtlib and generate a CMake source file from it. If that script fails,
# a fatal error occurs.
#
# EDT_PICKLE_FILE <file> : Input edtlib.EDT object in pickle format
# TARGET <target> : Target to populate with devicetree properties
#
function(zephyr_dt_import)
set(req_single_args "EDT_PICKLE_FILE;TARGET")
cmake_parse_arguments(arg "" "${req_single_args}" "" ${ARGN})
zephyr_check_arguments_required_all(${CMAKE_CURRENT_FUNCTION} arg ${req_single_args})
set(gen_dts_cmake_script ${ZEPHYR_BASE}/scripts/dts/gen_dts_cmake.py)
set(gen_dts_cmake_output ${arg_EDT_PICKLE_FILE}.cmake)
if((${arg_EDT_PICKLE_FILE} IS_NEWER_THAN ${gen_dts_cmake_output}) OR
(${gen_dts_cmake_script} IS_NEWER_THAN ${gen_dts_cmake_output})
)
execute_process(
COMMAND ${PYTHON_EXECUTABLE} ${gen_dts_cmake_script}
--edt-pickle ${arg_EDT_PICKLE_FILE}
--cmake-out ${gen_dts_cmake_output}
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
RESULT_VARIABLE ret
COMMAND_ERROR_IS_FATAL ANY
)
endif()
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${gen_dts_cmake_script})
set(DEVICETREE_TARGET ${arg_TARGET})
include(${gen_dts_cmake_output})
endfunction()
######################################################## ########################################################
# 5. Zephyr linker functions # 5. Zephyr linker functions
######################################################## ########################################################

20
scripts/dts/gen_dts_cmake.py

@ -11,13 +11,12 @@ That data can then be used in the rest of the build system.
The generated CMake file looks like this: The generated CMake file looks like this:
add_custom_target(devicetree_target) set_target_properties(${DEVICETREE_TARGET} PROPERTIES
set_target_properties(devicetree_target PROPERTIES
"DT_PROP|/soc|compatible" "vnd,soc;") "DT_PROP|/soc|compatible" "vnd,soc;")
... ...
It defines a special CMake target, and saves various values in the It takes an input variable - DEVICETREE_TARGET - and saves various
devicetree as CMake target properties. values in the devicetree as properties of this CMake target.
Be careful: Be careful:
@ -170,15 +169,12 @@ def main():
cmake_comp = f'DT_COMP|{comp}' cmake_comp = f'DT_COMP|{comp}'
cmake_props.append(f'"{cmake_comp}" "{cmake_path}"') cmake_props.append(f'"{cmake_comp}" "{cmake_path}"')
cmake_props = map(
'set_target_properties(${{DEVICETREE_TARGET}} PROPERTIES {})'.format,
cmake_props
)
with open(args.cmake_out, "w", encoding="utf-8") as cmake_file: with open(args.cmake_out, "w", encoding="utf-8") as cmake_file:
print('add_custom_target(devicetree_target)', file=cmake_file) print("\n".join(cmake_props), file=cmake_file)
print(file=cmake_file)
for prop in cmake_props:
print(
f'set_target_properties(devicetree_target PROPERTIES {prop})',
file=cmake_file
)
if __name__ == "__main__": if __name__ == "__main__":

Loading…
Cancel
Save