# Run chip code generation. # # Example usage: # chip_codegen("app" # INPUT "some_file.matter" # GENERATOR "bridge" # OUTPUTS # "bridge/OnOff.h" # "bridge/LevelControl.h" # "bridge/Switch.h" # # ... more outputs # OUTPUT_PATH DIR_NAME_VAR # OUTPUT_FILES FILE_NAMES_VAR # ) # # Arguments: # INPUT - the name of the ".matter" file to use for generation # GENERATOR - generator to use for codegen.py # OUTPUTS - EXPECTED output names. MUST match actual outputs # # OUTPUT_PATH - [OUT] output variable will contain the directory where the # files will be generated # OUTPUT_FILES - [OUT] output variable will contain the path of generated files. # suitable to be added within a build target # function(chip_codegen TARGET_NAME) cmake_parse_arguments(ARG "" "INPUT;GENERATOR;OUTPUT_PATH;OUTPUT_FILES" "OUTPUTS" ${ARGN} ) set(CHIP_CODEGEN_PREGEN_DIR "" CACHE PATH "Pre-generated directory to use instead of compile-time code generation.") if ("${CHIP_CODEGEN_PREGEN_DIR}" STREQUAL "") set(GEN_FOLDER "${CMAKE_BINARY_DIR}/gen/${TARGET_NAME}/${ARG_GENERATOR}") string(REPLACE ";" "\n" OUTPUT_AS_NEWLINES "${ARG_OUTPUTS}") file(MAKE_DIRECTORY "${GEN_FOLDER}") file(GENERATE OUTPUT "${GEN_FOLDER}/expected.outputs" CONTENT "${OUTPUT_AS_NEWLINES}" ) set(OUT_NAMES) foreach(NAME IN LISTS ARG_OUTPUTS) list(APPEND OUT_NAMES "${GEN_FOLDER}/${NAME}") endforeach() # Python is expected to be in the path # # find_package(Python3 REQUIRED) add_custom_command( OUTPUT ${OUT_NAMES} COMMAND "${CHIP_ROOT}/scripts/codegen.py" ARGS "--generator" "${ARG_GENERATOR}" "--output-dir" "${GEN_FOLDER}" "--expected-outputs" "${GEN_FOLDER}/expected.outputs" "${ARG_INPUT}" DEPENDS "${ARG_INPUT}" VERBATIM ) add_custom_target(${TARGET_NAME} DEPENDS "${OUT_NAMES}") # Forward outputs to the parent set(${ARG_OUTPUT_FILES} "${OUT_NAMES}" PARENT_SCOPE) set(${ARG_OUTPUT_PATH} "${GEN_FOLDER}" PARENT_SCOPE) else() # Gets a path such as: # examples/lock-app/lock-common/lock-app.matter file(RELATIVE_PATH MATTER_FILE_PATH "${CHIP_ROOT}" ${ARG_INPUT}) # Removes the trailing file extension to get something like: # examples/lock-app/lock-common/lock-app string(REGEX REPLACE "\.matter$" "" CODEGEN_DIR_PATH "${MATTER_FILE_PATH}") # Build the final location within the pregen directory set(GEN_FOLDER "${CHIP_CODEGEN_PREGEN_DIR}/${CODEGEN_DIR_PATH}/codegen/${ARG_GENERATOR}") # TODO: build a fake target of ${TARGET_NAME} # Here we have ${CHIP_CODEGEN_PREGEN_DIR} set(OUT_NAMES) foreach(NAME IN LISTS ARG_OUTPUTS) list(APPEND OUT_NAMES "${GEN_FOLDER}/${NAME}") endforeach() set(${ARG_OUTPUT_FILES} "${OUT_NAMES}" PARENT_SCOPE) set(${ARG_OUTPUT_PATH} "${GEN_FOLDER}" PARENT_SCOPE) # allow adding dependencies to a phony target since no codegen is done add_custom_target(${TARGET_NAME}) endif() endfunction() # Run chip code generation using zap # # Example usage: # chip_codegen("app" # INPUT "some_file.zap" # GENERATOR "app-templates" # OUTPUTS # "zap-generated/access.h", # "zap-generated/CHIPClusters.h" # "zap-generated/endpoint_config.h", # "zap-generated/gen_config.h", # "zap-generated/IMClusterCommandHandler.cpp" # OUTPUT_PATH DIR_NAME_VAR # OUTPUT_FILES FILE_NAMES_VAR # ) # # Arguments: # INPUT - the name of the ".zap" file to use for generation # GENERATOR - generator to use, like "app-templates" # OUTPUTS - EXPECTED output names # # OUTPUT_PATH - [OUT] output variable will contain the directory where the # files will be generated # # OUTPUT_FILES - [OUT] output variable will contain the path of generated files. # suitable to be added within a build target # function(chip_zapgen TARGET_NAME) cmake_parse_arguments(ARG "" "INPUT;GENERATOR;OUTPUT_PATH;OUTPUT_FILES" "OUTPUTS" ${ARGN} ) set(CHIP_CODEGEN_PREGEN_DIR "" CACHE PATH "Pre-generated directory to use instead of compile-time code generation.") if ("${CHIP_CODEGEN_PREGEN_DIR}" STREQUAL "") set(GEN_FOLDER "${CMAKE_BINARY_DIR}/gen/${TARGET_NAME}/zapgen/${ARG_GENERATOR}") string(REPLACE ";" "\n" OUTPUT_AS_NEWLINES "${ARG_OUTPUTS}") file(MAKE_DIRECTORY "${GEN_FOLDER}") file(GENERATE OUTPUT "${GEN_FOLDER}/expected.outputs" CONTENT "${OUTPUT_AS_NEWLINES}" ) set(OUT_NAMES) foreach(NAME IN LISTS ARG_OUTPUTS) list(APPEND OUT_NAMES "${GEN_FOLDER}/${NAME}") endforeach() if ("${ARG_GENERATOR}" STREQUAL "app-templates") SET(TEMPLATE_PATH "${CHIP_ROOT}/src/app/zap-templates/app-templates.json") # TODO: unclear how to maintain these: there is no parser that can figure # out links of template files and zap files and such SET(EXTRA_DEPENDENCIES "${CHIP_ROOT}/src/app/zap-templates/partials/header.zapt" "${CHIP_ROOT}/src/app/zap-templates/partials/im_command_handler_cluster_commands.zapt" "${CHIP_ROOT}/src/app/zap-templates/templates/app/access.zapt" "${CHIP_ROOT}/src/app/zap-templates/templates/app/CHIPClusters.zapt" "${CHIP_ROOT}/src/app/zap-templates/templates/app/endpoint_config.zapt" "${CHIP_ROOT}/src/app/zap-templates/templates/app/gen_config.zapt" "${CHIP_ROOT}/src/app/zap-templates/templates/app/im-cluster-command-handler.zapt" ) SET(OUTPUT_SUBDIR "zap-generated") else() message(SEND_ERROR "Unsupported zap generator: ${ARG_GENERATOR}") endif() # Python is expected to be in the path # # find_package(Python3 REQUIRED) # # TODO: lockfile support should be removed as this serializes zap # (slower), however this is currently done because on Darwin zap startup # may conflict and error out with: # Error: EEXIST: file already exists, mkdir '/var/folders/24/8k48jl6d249_n_qfxwsl6xvm0000gn/T/pkg/465fcc8a6282e28dc7a166859d5814d34e2fb94249a72fa9229033b5b32dff1a' add_custom_command( OUTPUT ${OUT_NAMES} COMMAND "${CHIP_ROOT}/scripts/tools/zap/generate.py" ARGS "--no-prettify-output" "--templates" "${TEMPLATE_PATH}" "--output-dir" "${GEN_FOLDER}/${OUTPUT_SUBDIR}" "--lock-file" "${CMAKE_BINARY_DIR}/zap_gen.lock" "--parallel" "${ARG_INPUT}" DEPENDS "${ARG_INPUT}" ${EXTRA_DEPENDENCIES} VERBATIM ) add_custom_target(${TARGET_NAME} DEPENDS "${OUT_NAMES}") # Forward outputs to the parent set(${ARG_OUTPUT_FILES} "${OUT_NAMES}" PARENT_SCOPE) set(${ARG_OUTPUT_PATH} "${GEN_FOLDER}" PARENT_SCOPE) else() # Gets a path such as: # examples/lock-app/lock-common/lock-app.zap file(RELATIVE_PATH MATTER_FILE_PATH "${CHIP_ROOT}" ${ARG_INPUT}) # Removes the trailing file extension to get something like: # examples/lock-app/lock-common/lock-app string(REGEX REPLACE "\.zap$" "" CODEGEN_DIR_PATH "${MATTER_FILE_PATH}") # Build the final location within the pregen directory set(GEN_FOLDER "${CHIP_CODEGEN_PREGEN_DIR}/${CODEGEN_DIR_PATH}/zap/${ARG_GENERATOR}") # TODO: build a fake target of ${TARGET_NAME} # Here we have ${CHIP_CODEGEN_PREGEN_DIR} set(OUT_NAMES) foreach(NAME IN LISTS ARG_OUTPUTS) list(APPEND OUT_NAMES "${GEN_FOLDER}/${NAME}") endforeach() set(${ARG_OUTPUT_FILES} "${OUT_NAMES}" PARENT_SCOPE) set(${ARG_OUTPUT_PATH} "${GEN_FOLDER}" PARENT_SCOPE) # allow adding dependencies to a phony target since no codegen is done add_custom_target(${TARGET_NAME}) endif() endfunction()