• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (c) 2021-2022 Huawei Device Co., Ltd.
2# Licensed under the Apache License, Version 2.0 (the "License");
3# you may not use this file except in compliance with the License.
4# You may obtain a copy of the License at
5#
6# http://www.apache.org/licenses/LICENSE-2.0
7#
8# Unless required by applicable law or agreed to in writing, software
9# distributed under the License is distributed on an "AS IS" BASIS,
10# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11# See the License for the specific language governing permissions and
12# limitations under the License.
13
14cmake_minimum_required(VERSION 3.5.2 FATAL_ERROR)
15
16# Generate files based on templates and YAML data provided.
17# Adds targets for every template. Also adds a target for the whole function invocation
18# with name ${data_name}_gen_${PROJECT_NAME} for ease of declaring dependencies on generated files.
19#
20# Mandatory arguments:
21# * DATA -- data source, YAML file
22# * TEMPLATES -- a list of templates to generate files
23# * REQUIRES -- a list of Ruby scripts that provide data-querying API for templates
24#
25# Optional arguments:
26# * SOURCE -- a directory with templates, default is ${PROJECT_SOURCE_DIR}/templates
27# * DESTINATION -- a directory for output files, default is ${PANDA_BINARY_ROOT}
28# * EXTRA_DEPENDENCIES -- a list of files that should be considered as dependencies
29# * EXTRA_ARGV -- a list of positional arguments that could be accessed in '.erb' files via ARGV[]
30
31function(panda_gen)
32    set(singlevalues DATA SOURCE DESTINATION TARGET_NAME)
33    set(multivalues TEMPLATES REQUIRES EXTRA_DEPENDENCIES EXTRA_ARGV)
34    cmake_parse_arguments(
35        GEN_ARG
36        ""
37        "${singlevalues}"
38        "${multivalues}"
39        ${ARGN}
40    )
41
42    if (NOT DEFINED GEN_ARG_TEMPLATES)
43        message(FATAL_ERROR "`TEMPLATES` were not passed to `panda_gen` function")
44    endif()
45
46    if (NOT DEFINED GEN_ARG_DATA)
47        message(FATAL_ERROR "`DATA` was not passed to `panda_gen` function")
48    endif()
49
50    if (NOT DEFINED GEN_ARG_SOURCE)
51        set(GEN_ARG_SOURCE "${PROJECT_SOURCE_DIR}/templates")
52    endif()
53
54    if (NOT DEFINED GEN_ARG_DESTINATION)
55        set(GEN_ARG_DESTINATION "${CMAKE_CURRENT_BINARY_DIR}")
56    endif()
57
58    if (NOT DEFINED GEN_ARG_TARGET_NAME)
59        get_filename_component(DATA_NAME ${GEN_ARG_DATA} NAME_WE)
60        set(GEN_ARG_TARGET_NAME "${DATA_NAME}_gen_${PROJECT_NAME}")
61    endif()
62
63    add_custom_target(${GEN_ARG_TARGET_NAME}) # Umbrella target for all generated files
64
65    foreach(t ${GEN_ARG_TEMPLATES})
66        set(TEMPLATE "${GEN_ARG_SOURCE}/${t}")
67        string(REGEX REPLACE "\.erb$" "" NAME ${t})
68        string(REPLACE "\." "_" TARGET ${NAME})
69        string(REPLACE "/" "_" TARGET ${TARGET})
70        set(TARGET ${PROJECT_NAME}_${TARGET})
71        set(OUTPUT_FILE "${GEN_ARG_DESTINATION}/${NAME}")
72
73        panda_gen_file(DATAFILE ${GEN_ARG_DATA}
74            TEMPLATE ${TEMPLATE}
75            OUTPUTFILE ${OUTPUT_FILE}
76            REQUIRES ${GEN_ARG_REQUIRES}
77            EXTRA_DEPENDENCIES ${GEN_ARG_EXTRA_DEPENDENCIES}
78            EXTRA_ARGV ${GEN_ARG_EXTRA_ARGV}
79        )
80        add_custom_target(${TARGET} DEPENDS ${OUTPUT_FILE})
81        add_dependencies(${GEN_ARG_TARGET_NAME} ${TARGET})
82    endforeach()
83endfunction()
84
85# Calls `panda_gen` for ISA YAML.
86# Adds targets for every template. Also adds a target for the whole function invocation
87# with name isa_gen_${PROJECT_NAME} for ease of declaring dependencies on generated files.
88#
89# Mandatory arguments:
90# * TEMPLATES -- a list of templates to generate files
91#
92# Optional arguments:
93# * SOURCE -- a directory with templates, default is ${PROJECT_SOURCE_DIR}/templates
94# * DESTINATION -- a directory for output files, default is ${PANDA_BINARY_ROOT}
95# * REQUIRES -- if defined, will require additional Ruby files for template generation
96# * EXTRA_DEPENDENCIES -- a list of files that should be considered as dependencies
97
98function(panda_isa_gen)
99    set(singlevalues SOURCE DESTINATION)
100    set(multivalues TEMPLATES REQUIRES EXTRA_DEPENDENCIES)
101    cmake_parse_arguments(
102        ISA_GEN_ARG
103        ""
104        "${singlevalues}"
105        "${multivalues}"
106        ${ARGN}
107    )
108    set(ISA_DATA "${CMAKE_BINARY_DIR}/isa/isa.yaml")
109    set(ISAPI "${PANDA_ROOT}/isa/isapi.rb")
110    list(INSERT ISA_GEN_ARG_REQUIRES 0 ${ISAPI})
111    list(APPEND ISA_GEN_ARG_EXTRA_DEPENDENCIES isa_assert)
112    panda_gen(DATA ${ISA_DATA}
113        TEMPLATES ${ISA_GEN_ARG_TEMPLATES}
114        SOURCE ${ISA_GEN_ARG_SOURCE}
115        DESTINATION ${ISA_GEN_ARG_DESTINATION}
116        REQUIRES ${ISA_GEN_ARG_REQUIRES}
117        EXTRA_DEPENDENCIES ${ISA_GEN_ARG_EXTRA_DEPENDENCIES}
118    )
119endfunction()
120
121# Generate file for a template and YAML data provided.
122#
123# Mandatory arguments:
124# DATAFILE -- YAML data full name
125# TEMPLATE -- template full name
126# OUTPUTFILE -- output file full name
127# REQUIRES -- a list of scripts that provide data-querying API for templates
128# EXTRA_DEPENDENCIES -- a list of files that should be considered as dependencies
129# EXTRA_ARGV -- a list of positional arguments that could be accessed in '.erb' files via ARGV[]
130
131function(panda_gen_file)
132    set(singlevalues DATAFILE TEMPLATE OUTPUTFILE)
133    set(multivalues REQUIRES EXTRA_DEPENDENCIES EXTRA_ARGV)
134    cmake_parse_arguments(
135        ARG
136        ""
137        "${singlevalues}"
138        "${multivalues}"
139        ${ARGN}
140    )
141    set(GENERATOR "${PANDA_ROOT}/isa/gen.rb")
142    string(REPLACE ";" "," REQUIRE_STR "${ARG_REQUIRES}")
143    set(DEPENDS_LIST ${GENERATOR} ${ARG_TEMPLATE} ${ARG_DATAFILE})
144
145    add_custom_command(OUTPUT ${ARG_OUTPUTFILE}
146        COMMENT "Generate file for ${ARG_TEMPLATE}"
147        COMMAND ${GENERATOR} ${ARG_EXTRA_ARGV} --template ${ARG_TEMPLATE} --data ${ARG_DATAFILE} --output ${ARG_OUTPUTFILE} --require ${REQUIRE_STR}
148        DEPENDS ${DEPENDS_LIST} ${ARG_EXTRA_DEPENDENCIES} ${ARG_REQUIRES}
149    )
150endfunction()
151
152# Create an options header using a YAML file for the target
153#
154# Mandatory arguments:
155# TARGET -- target
156# YAML_FILE -- YAML file
157# GENERATED_HEADER -- generated header
158#
159# Use "#include 'generated/GENERATED_HEADER"' to include the generated header
160
161function(panda_gen_options)
162    # Parsing function arguments
163    set(singlevalues TARGET YAML_FILE GENERATED_HEADER)
164    cmake_parse_arguments(GEN_OPTIONS "" "${singlevalues}" "" ${ARGN})
165
166    # Generate a options header
167    get_filename_component(YAML_FILE ${GEN_OPTIONS_YAML_FILE} ABSOLUTE)
168    set(GENERATED_DIR ${CMAKE_CURRENT_BINARY_DIR}/panda_gen_options/generated)
169    file(MAKE_DIRECTORY ${GENERATED_DIR})
170    set(OPTIONS_H ${GENERATED_DIR}/${GEN_OPTIONS_GENERATED_HEADER})
171    panda_gen_file(
172        DATAFILE ${YAML_FILE}
173        TEMPLATE ${PANDA_ROOT}/templates/options/options.h.erb
174        OUTPUTFILE ${OPTIONS_H}
175        REQUIRES ${PANDA_ROOT}/templates/common.rb
176    )
177
178    # Add dependencies for a target
179    target_include_directories(${GEN_OPTIONS_TARGET} PUBLIC ${GENERATED_DIR}/..)
180    add_custom_target(${GEN_OPTIONS_TARGET}_options DEPENDS ${OPTIONS_H})
181    add_dependencies(${GEN_OPTIONS_TARGET} ${GEN_OPTIONS_TARGET}_options)
182endfunction()
183
184function(panda_gen_messages)
185    set(singlevalues TARGET YAML_FILE GENERATED_HEADER)
186    cmake_parse_arguments(ARG "" "${singlevalues}" "" ${ARGN})
187
188    if(NOT DEFINED ARG_YAML_FILE)
189        set(ARG_YAML_FILE ${CMAKE_CURRENT_SOURCE_DIR}/messages.yaml)
190    endif()
191
192    if(NOT DEFINED ARG_GENERATED_HEADER)
193        set(ARG_GENERATED_HEADER messages.h)
194    endif()
195
196    get_filename_component(YAML_FILE ${ARG_YAML_FILE} ABSOLUTE)
197
198    if(IS_ABSOLUTE ${ARG_GENERATED_HEADER})
199        get_filename_component(GENERATED_DIR ${ARG_GENERATED_HEADER} DIRECTORY)
200        set(MESSAGES_H ${ARG_GENERATED_HEADER})
201    else()
202        set(INCLUDE_DIR ${CMAKE_CURRENT_BINARY_DIR}/panda_gen_messages)
203        set(GENERATED_DIR ${INCLUDE_DIR}/generated)
204        set(MESSAGES_H ${GENERATED_DIR}/${ARG_GENERATED_HEADER})
205    endif()
206
207    file(MAKE_DIRECTORY ${GENERATED_DIR})
208    panda_gen_file(
209        DATAFILE ${YAML_FILE}
210        TEMPLATE ${PANDA_ROOT}/templates/messages/messages.h.erb
211        OUTPUTFILE ${MESSAGES_H}
212        REQUIRES ${PANDA_ROOT}/templates/messages.rb
213    )
214
215    # Add dependencies for a target
216    if (NOT DEFINED ARG_TARGET)
217        set(ARG_TARGET messages_gen_${PROJECT_NAME})
218        add_custom_target(${ARG_TARGET})
219    endif()
220
221    if (DEFINED INCLUDE_DIR)
222        target_include_directories(${ARG_TARGET} PUBLIC ${INCLUDE_DIR})
223    endif()
224    add_custom_target(${ARG_TARGET}_messages DEPENDS ${MESSAGES_H})
225    add_dependencies(${ARG_TARGET} ${ARG_TARGET}_messages)
226endfunction()
227
228add_custom_target(plugin_options_gen)
229set_target_properties(plugin_options_gen PROPERTIES PLUGIN_OPTIONS_YAML_FILES "${PANDA_ROOT}/templates/plugin_options.yaml")
230
231add_custom_target(entrypoints_yaml_gen)
232set_target_properties(entrypoints_yaml_gen PROPERTIES ENTRYPOINT_YAML_FILES "${PANDA_ROOT}/runtime/entrypoints/entrypoints.yaml")
233
234add_custom_target(runtime_options_gen)
235set_target_properties(runtime_options_gen PROPERTIES RUNTIME_OPTIONS_YAML_FILES "${PANDA_ROOT}/runtime/options.yaml")
236
237function(add_plugin_options YAML_FILE_PATH)
238    get_target_property(YAML_FILES plugin_options_gen PLUGIN_OPTIONS_YAML_FILES)
239    list(APPEND YAML_FILES ${YAML_FILE_PATH})
240    set_target_properties(plugin_options_gen PROPERTIES PLUGIN_OPTIONS_YAML_FILES "${YAML_FILES}")
241endfunction()
242
243function(add_entrypoints_yaml YAML_FILE_PATH)
244    get_target_property(YAML_FILES entrypoints_yaml_gen ENTRYPOINT_YAML_FILES)
245    list(APPEND YAML_FILES ${YAML_FILE_PATH})
246    set_target_properties(entrypoints_yaml_gen PROPERTIES ENTRYPOINT_YAML_FILES "${YAML_FILES}")
247endfunction()
248
249function(add_runtime_options YAML_FILE_PATH)
250    get_target_property(YAML_FILES runtime_options_gen RUNTIME_OPTIONS_YAML_FILES)
251    list(APPEND YAML_FILES ${YAML_FILE_PATH})
252    set_target_properties(runtime_options_gen PROPERTIES RUNTIME_OPTIONS_YAML_FILES "${YAML_FILES}")
253endfunction()
254