chip_codegen.cmake 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. # Run chip code generation.
  2. #
  3. # Example usage:
  4. # chip_codegen("app"
  5. # INPUT "some_file.matter"
  6. # GENERATOR "bridge"
  7. # OUTPUTS
  8. # "bridge/OnOff.h"
  9. # "bridge/LevelControl.h"
  10. # "bridge/Switch.h"
  11. # # ... more outputs
  12. # OUTPUT_PATH DIR_NAME_VAR
  13. # OUTPUT_FILES FILE_NAMES_VAR
  14. # )
  15. #
  16. # Arguments:
  17. # INPUT - the name of the ".matter" file to use for generation
  18. # GENERATOR - generator to use for codegen.py
  19. # OUTPUTS - EXPECTED output names. MUST match actual outputs
  20. #
  21. # OUTPUT_PATH - [OUT] output variable will contain the directory where the
  22. # files will be generated
  23. # OUTPUT_FILES - [OUT] output variable will contain the path of generated files.
  24. # suitable to be added within a build target
  25. #
  26. function(chip_codegen TARGET_NAME)
  27. cmake_parse_arguments(ARG
  28. ""
  29. "INPUT;GENERATOR;OUTPUT_PATH;OUTPUT_FILES"
  30. "OUTPUTS"
  31. ${ARGN}
  32. )
  33. set(CHIP_CODEGEN_PREGEN_DIR "" CACHE PATH "Pre-generated directory to use instead of compile-time code generation.")
  34. if ("${CHIP_CODEGEN_PREGEN_DIR}" STREQUAL "")
  35. set(GEN_FOLDER "${CMAKE_BINARY_DIR}/gen/${TARGET_NAME}/${ARG_GENERATOR}")
  36. string(REPLACE ";" "\n" OUTPUT_AS_NEWLINES "${ARG_OUTPUTS}")
  37. file(MAKE_DIRECTORY "${GEN_FOLDER}")
  38. file(GENERATE
  39. OUTPUT "${GEN_FOLDER}/expected.outputs"
  40. CONTENT "${OUTPUT_AS_NEWLINES}"
  41. )
  42. set(OUT_NAMES)
  43. foreach(NAME IN LISTS ARG_OUTPUTS)
  44. list(APPEND OUT_NAMES "${GEN_FOLDER}/${NAME}")
  45. endforeach()
  46. # Python is expected to be in the path
  47. #
  48. # find_package(Python3 REQUIRED)
  49. add_custom_command(
  50. OUTPUT ${OUT_NAMES}
  51. COMMAND "${CHIP_ROOT}/scripts/codegen.py"
  52. ARGS "--generator" "${ARG_GENERATOR}"
  53. "--output-dir" "${GEN_FOLDER}"
  54. "--expected-outputs" "${GEN_FOLDER}/expected.outputs"
  55. "${ARG_INPUT}"
  56. DEPENDS
  57. "${ARG_INPUT}"
  58. VERBATIM
  59. )
  60. add_custom_target(${TARGET_NAME} DEPENDS "${OUT_NAMES}")
  61. # Forward outputs to the parent
  62. set(${ARG_OUTPUT_FILES} "${OUT_NAMES}" PARENT_SCOPE)
  63. set(${ARG_OUTPUT_PATH} "${GEN_FOLDER}" PARENT_SCOPE)
  64. else()
  65. # Gets a path such as:
  66. # examples/lock-app/lock-common/lock-app.matter
  67. file(RELATIVE_PATH MATTER_FILE_PATH "${CHIP_ROOT}" ${ARG_INPUT})
  68. # Removes the trailing file extension to get something like:
  69. # examples/lock-app/lock-common/lock-app
  70. string(REGEX REPLACE "\.matter$" "" CODEGEN_DIR_PATH "${MATTER_FILE_PATH}")
  71. # Build the final location within the pregen directory
  72. set(GEN_FOLDER "${CHIP_CODEGEN_PREGEN_DIR}/${CODEGEN_DIR_PATH}/codegen/${ARG_GENERATOR}")
  73. # TODO: build a fake target of ${TARGET_NAME}
  74. # Here we have ${CHIP_CODEGEN_PREGEN_DIR}
  75. set(OUT_NAMES)
  76. foreach(NAME IN LISTS ARG_OUTPUTS)
  77. list(APPEND OUT_NAMES "${GEN_FOLDER}/${NAME}")
  78. endforeach()
  79. set(${ARG_OUTPUT_FILES} "${OUT_NAMES}" PARENT_SCOPE)
  80. set(${ARG_OUTPUT_PATH} "${GEN_FOLDER}" PARENT_SCOPE)
  81. # allow adding dependencies to a phony target since no codegen is done
  82. add_custom_target(${TARGET_NAME})
  83. endif()
  84. endfunction()
  85. # Run chip code generation using zap
  86. #
  87. # Example usage:
  88. # chip_codegen("app"
  89. # INPUT "some_file.zap"
  90. # GENERATOR "app-templates"
  91. # OUTPUTS
  92. # "zap-generated/access.h",
  93. # "zap-generated/CHIPClusters.h"
  94. # "zap-generated/endpoint_config.h",
  95. # "zap-generated/gen_config.h",
  96. # "zap-generated/IMClusterCommandHandler.cpp"
  97. # OUTPUT_PATH DIR_NAME_VAR
  98. # OUTPUT_FILES FILE_NAMES_VAR
  99. # )
  100. #
  101. # Arguments:
  102. # INPUT - the name of the ".zap" file to use for generation
  103. # GENERATOR - generator to use, like "app-templates"
  104. # OUTPUTS - EXPECTED output names
  105. #
  106. # OUTPUT_PATH - [OUT] output variable will contain the directory where the
  107. # files will be generated
  108. #
  109. # OUTPUT_FILES - [OUT] output variable will contain the path of generated files.
  110. # suitable to be added within a build target
  111. #
  112. function(chip_zapgen TARGET_NAME)
  113. cmake_parse_arguments(ARG
  114. ""
  115. "INPUT;GENERATOR;OUTPUT_PATH;OUTPUT_FILES"
  116. "OUTPUTS"
  117. ${ARGN}
  118. )
  119. set(CHIP_CODEGEN_PREGEN_DIR "" CACHE PATH "Pre-generated directory to use instead of compile-time code generation.")
  120. if ("${CHIP_CODEGEN_PREGEN_DIR}" STREQUAL "")
  121. set(GEN_FOLDER "${CMAKE_BINARY_DIR}/gen/${TARGET_NAME}/zapgen/${ARG_GENERATOR}")
  122. string(REPLACE ";" "\n" OUTPUT_AS_NEWLINES "${ARG_OUTPUTS}")
  123. file(MAKE_DIRECTORY "${GEN_FOLDER}")
  124. file(GENERATE
  125. OUTPUT "${GEN_FOLDER}/expected.outputs"
  126. CONTENT "${OUTPUT_AS_NEWLINES}"
  127. )
  128. set(OUT_NAMES)
  129. foreach(NAME IN LISTS ARG_OUTPUTS)
  130. list(APPEND OUT_NAMES "${GEN_FOLDER}/${NAME}")
  131. endforeach()
  132. if ("${ARG_GENERATOR}" STREQUAL "app-templates")
  133. SET(TEMPLATE_PATH "${CHIP_ROOT}/src/app/zap-templates/app-templates.json")
  134. # TODO: unclear how to maintain these: there is no parser that can figure
  135. # out links of template files and zap files and such
  136. SET(EXTRA_DEPENDENCIES
  137. "${CHIP_ROOT}/src/app/zap-templates/partials/header.zapt"
  138. "${CHIP_ROOT}/src/app/zap-templates/partials/im_command_handler_cluster_commands.zapt"
  139. "${CHIP_ROOT}/src/app/zap-templates/templates/app/access.zapt"
  140. "${CHIP_ROOT}/src/app/zap-templates/templates/app/CHIPClusters.zapt"
  141. "${CHIP_ROOT}/src/app/zap-templates/templates/app/endpoint_config.zapt"
  142. "${CHIP_ROOT}/src/app/zap-templates/templates/app/gen_config.zapt"
  143. "${CHIP_ROOT}/src/app/zap-templates/templates/app/im-cluster-command-handler.zapt"
  144. )
  145. SET(OUTPUT_SUBDIR "zap-generated")
  146. else()
  147. message(SEND_ERROR "Unsupported zap generator: ${ARG_GENERATOR}")
  148. endif()
  149. # Python is expected to be in the path
  150. #
  151. # find_package(Python3 REQUIRED)
  152. #
  153. # TODO: lockfile support should be removed as this serializes zap
  154. # (slower), however this is currently done because on Darwin zap startup
  155. # may conflict and error out with:
  156. # Error: EEXIST: file already exists, mkdir '/var/folders/24/8k48jl6d249_n_qfxwsl6xvm0000gn/T/pkg/465fcc8a6282e28dc7a166859d5814d34e2fb94249a72fa9229033b5b32dff1a'
  157. add_custom_command(
  158. OUTPUT ${OUT_NAMES}
  159. COMMAND "${CHIP_ROOT}/scripts/tools/zap/generate.py"
  160. ARGS
  161. "--no-prettify-output"
  162. "--templates" "${TEMPLATE_PATH}"
  163. "--output-dir" "${GEN_FOLDER}/${OUTPUT_SUBDIR}"
  164. "--lock-file" "${CMAKE_BINARY_DIR}/zap_gen.lock"
  165. "--parallel"
  166. "${ARG_INPUT}"
  167. DEPENDS
  168. "${ARG_INPUT}"
  169. ${EXTRA_DEPENDENCIES}
  170. VERBATIM
  171. )
  172. add_custom_target(${TARGET_NAME} DEPENDS "${OUT_NAMES}")
  173. # Forward outputs to the parent
  174. set(${ARG_OUTPUT_FILES} "${OUT_NAMES}" PARENT_SCOPE)
  175. set(${ARG_OUTPUT_PATH} "${GEN_FOLDER}" PARENT_SCOPE)
  176. else()
  177. # Gets a path such as:
  178. # examples/lock-app/lock-common/lock-app.zap
  179. file(RELATIVE_PATH MATTER_FILE_PATH "${CHIP_ROOT}" ${ARG_INPUT})
  180. # Removes the trailing file extension to get something like:
  181. # examples/lock-app/lock-common/lock-app
  182. string(REGEX REPLACE "\.zap$" "" CODEGEN_DIR_PATH "${MATTER_FILE_PATH}")
  183. # Build the final location within the pregen directory
  184. set(GEN_FOLDER "${CHIP_CODEGEN_PREGEN_DIR}/${CODEGEN_DIR_PATH}/zap/${ARG_GENERATOR}")
  185. # TODO: build a fake target of ${TARGET_NAME}
  186. # Here we have ${CHIP_CODEGEN_PREGEN_DIR}
  187. set(OUT_NAMES)
  188. foreach(NAME IN LISTS ARG_OUTPUTS)
  189. list(APPEND OUT_NAMES "${GEN_FOLDER}/${NAME}")
  190. endforeach()
  191. set(${ARG_OUTPUT_FILES} "${OUT_NAMES}" PARENT_SCOPE)
  192. set(${ARG_OUTPUT_PATH} "${GEN_FOLDER}" PARENT_SCOPE)
  193. # allow adding dependencies to a phony target since no codegen is done
  194. add_custom_target(${TARGET_NAME})
  195. endif()
  196. endfunction()