• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (c) 2021-2024 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 -- a list of data sources, YAML files
22# * API -- a list of Ruby scripts that provide data-querying API for templates
23#   (Nth script from API should parse Nth YAML file from DATA)
24# * TEMPLATES -- a list of templates to generate files
25#
26# Optional arguments:
27# * SOURCE -- a directory with templates, default is ${PROJECT_SOURCE_DIR}/templates
28# * DESTINATION -- a directory for output files, default is ${PANDA_BINARY_ROOT}
29# * REQUIRES -- if defined, will require additional Ruby files for template generation
30# * EXTRA_DEPENDENCIES -- a list of files that should be considered as dependencies
31# * EXTRA_ARGV -- a list of positional arguments that could be accessed in '.erb' files via ARGV[]
32
33function(panda_gen)
34    set(singlevalues SOURCE DESTINATION TARGET_NAME)
35    set(multivalues DATA API TEMPLATES REQUIRES EXTRA_DEPENDENCIES EXTRA_ARGV)
36    cmake_parse_arguments(
37        GEN_ARG
38        ""
39        "${singlevalues}"
40        "${multivalues}"
41        ${ARGN}
42    )
43
44    if (NOT DEFINED GEN_ARG_TEMPLATES)
45        message(FATAL_ERROR "`TEMPLATES` were not passed to `panda_gen` function")
46    endif()
47
48    if (NOT DEFINED GEN_ARG_DATA)
49        message(FATAL_ERROR "`DATA` was not passed to `panda_gen` function")
50    endif()
51
52    if (NOT DEFINED GEN_ARG_API)
53        message(FATAL_ERROR "`API` was not passed to `panda_gen` function")
54    endif()
55
56    if (NOT DEFINED GEN_ARG_SOURCE)
57        set(GEN_ARG_SOURCE "${PROJECT_SOURCE_DIR}/templates")
58    endif()
59
60    if (NOT DEFINED GEN_ARG_DESTINATION)
61        set(GEN_ARG_DESTINATION "${CMAKE_CURRENT_BINARY_DIR}")
62    endif()
63
64    if (NOT DEFINED GEN_ARG_TARGET_NAME)
65        get_filename_component(DATA_NAME ${GEN_ARG_DATA} NAME_WE)
66        set(GEN_ARG_TARGET_NAME "${DATA_NAME}_gen_${PROJECT_NAME}")
67    endif()
68
69    add_custom_target(${GEN_ARG_TARGET_NAME}) # Umbrella target for all generated files
70    add_dependencies(panda_gen_files ${GEN_ARG_TARGET_NAME})
71
72    foreach(t ${GEN_ARG_TEMPLATES})
73        set(TEMPLATE "${GEN_ARG_SOURCE}/${t}")
74        string(REGEX REPLACE "\.erb$" "" NAME ${t})
75        string(REPLACE "\." "_" TARGET ${NAME})
76        string(REPLACE "/" "_" TARGET ${TARGET})
77        set(TARGET ${PROJECT_NAME}_${TARGET})
78        set(OUTPUT_FILE "${GEN_ARG_DESTINATION}/${NAME}")
79
80        panda_gen_file(DATA ${GEN_ARG_DATA}
81            API ${GEN_ARG_API}
82            TEMPLATE ${TEMPLATE}
83            OUTPUTFILE ${OUTPUT_FILE}
84            REQUIRES ${GEN_ARG_REQUIRES}
85            EXTRA_DEPENDENCIES ${GEN_ARG_EXTRA_DEPENDENCIES}
86            EXTRA_ARGV ${GEN_ARG_EXTRA_ARGV}
87        )
88        add_custom_target(${TARGET} DEPENDS ${OUTPUT_FILE})
89        add_dependencies(${GEN_ARG_TARGET_NAME} ${TARGET})
90    endforeach()
91endfunction()
92
93# Calls `panda_gen` for ISA YAML.
94# Adds targets for every template. Also adds a target for the whole function invocation
95# with name isa_gen_${PROJECT_NAME} for ease of declaring dependencies on generated files.
96#
97# Mandatory arguments:
98# * TEMPLATES -- a list of templates to generate files
99#
100# Optional arguments:
101# * SOURCE -- a directory with templates, default is ${PROJECT_SOURCE_DIR}/templates
102# * DESTINATION -- a directory for output files, default is ${PANDA_BINARY_ROOT}
103# * REQUIRES -- if defined, will require additional Ruby files for template generation
104# * EXTRA_DEPENDENCIES -- a list of files that should be considered as dependencies
105
106function(panda_isa_gen)
107    set(singlevalues SOURCE DESTINATION TARGET_NAME)
108    set(multivalues TEMPLATES REQUIRES EXTRA_DEPENDENCIES)
109    cmake_parse_arguments(
110        ISA_GEN_ARG
111        ""
112        "${singlevalues}"
113        "${multivalues}"
114        ${ARGN}
115    )
116    set(ISA_DATA "${CMAKE_BINARY_DIR}/isa/isa.yaml")
117    set(ISAPI "${PANDA_ROOT}/isa/isapi.rb")
118    list(APPEND ISA_GEN_ARG_EXTRA_DEPENDENCIES isa_assert)
119    panda_gen(DATA ${ISA_DATA}
120        API ${ISAPI}
121        TEMPLATES ${ISA_GEN_ARG_TEMPLATES}
122        SOURCE ${ISA_GEN_ARG_SOURCE}
123        TARGET_NAME ${ISA_GEN_ARG_TARGET_NAME}
124        DESTINATION ${ISA_GEN_ARG_DESTINATION}
125        REQUIRES ${ISA_GEN_ARG_REQUIRES}
126        EXTRA_DEPENDENCIES ${ISA_GEN_ARG_EXTRA_DEPENDENCIES}
127    )
128endfunction()
129
130# Generate file for a template and YAML data provided.
131#
132# Mandatory arguments:
133# * DATA -- a list of data sources, YAML files
134# * API -- a list of Ruby scripts that provide data-querying API for templates
135#   (Nth script from API should parse Nth YAML file from DATA)
136# * TEMPLATE -- template full name
137# * OUTPUTFILE -- output file full name
138#
139# Optional arguments:
140# * REQUIRES -- if defined, will require additional Ruby files for template generation
141# * EXTRA_DEPENDENCIES -- a list of files that should be considered as dependencies
142# * EXTRA_ARGV -- a list of positional arguments that could be accessed in '.erb' files via ARGV[]
143
144function(panda_gen_file)
145    set(singlevalues TEMPLATE OUTPUTFILE)
146    set(multivalues DATA API REQUIRES EXTRA_DEPENDENCIES EXTRA_ARGV)
147    cmake_parse_arguments(
148        ARG
149        ""
150        "${singlevalues}"
151        "${multivalues}"
152        ${ARGN}
153    )
154    if (NOT DEFINED ARG_TEMPLATE)
155        message(FATAL_ERROR "`TEMPLATE` was not passed to `panda_gen_file` function")
156    endif()
157    if (NOT DEFINED ARG_DATA)
158        message(FATAL_ERROR "`DATA` was not passed to `panda_gen_file` function")
159    endif()
160    if (NOT DEFINED ARG_API)
161        message(FATAL_ERROR "`API` was not passed to `panda_gen_file` function")
162    endif()
163    set(GENERATOR "${PANDA_ROOT}/isa/gen.rb")
164    string(REPLACE ";" "," DATA_STR "${ARG_DATA}")
165    string(REPLACE ";" "," API_STR "${ARG_API}")
166    if(DEFINED ARG_REQUIRES)
167        string(REPLACE ";" "," REQUIRE_STR "${ARG_REQUIRES}")
168        set(REQUIRE_OPTION --require ${REQUIRE_STR})
169    endif()
170    set(DEPENDS_LIST ${GENERATOR} ${ARG_TEMPLATE} ${ARG_DATA} ${ARG_API})
171
172
173    add_custom_command(OUTPUT ${ARG_OUTPUTFILE}
174        COMMENT "Generate file for ${ARG_TEMPLATE}"
175        COMMAND ${GENERATOR} ${ARG_EXTRA_ARGV} --template ${ARG_TEMPLATE} --data ${DATA_STR} --api ${API_STR} --output ${ARG_OUTPUTFILE} ${REQUIRE_OPTION}
176        DEPENDS ${DEPENDS_LIST} ${ARG_EXTRA_DEPENDENCIES}
177    )
178endfunction()
179
180# Create an options header using a YAML file for the target
181#
182# Mandatory arguments:
183# TARGET -- target
184# YAML_FILE -- YAML file
185# GENERATED_HEADER -- generated header
186#
187# Use "#include 'generated/GENERATED_HEADER"' to include the generated header
188
189function(panda_gen_options)
190    # Parsing function arguments
191    set(singlevalues TARGET YAML_FILE GENERATED_HEADER)
192    cmake_parse_arguments(GEN_OPTIONS "" "${singlevalues}" "" ${ARGN})
193
194    # Generate a options header
195    get_filename_component(YAML_FILE ${GEN_OPTIONS_YAML_FILE} ABSOLUTE)
196    set(GENERATED_DIR ${CMAKE_CURRENT_BINARY_DIR}/panda_gen_options/generated)
197    file(MAKE_DIRECTORY ${GENERATED_DIR})
198    set(OPTIONS_H ${GENERATED_DIR}/${GEN_OPTIONS_GENERATED_HEADER})
199    panda_gen_file(
200        DATA ${YAML_FILE}
201        TEMPLATE ${PANDA_ROOT}/templates/options/options.h.erb
202        OUTPUTFILE ${OPTIONS_H}
203        API ${PANDA_ROOT}/templates/common.rb
204    )
205
206    # Add dependencies for a target
207    panda_target_include_directories(${GEN_OPTIONS_TARGET} PUBLIC ${GENERATED_DIR}/..)
208    add_custom_target(${GEN_OPTIONS_TARGET}_options DEPENDS ${OPTIONS_H})
209    add_dependencies(${GEN_OPTIONS_TARGET} ${GEN_OPTIONS_TARGET}_options)
210    add_dependencies(panda_gen_files ${GEN_OPTIONS_TARGET}_options)
211endfunction()
212
213function(panda_gen_messages)
214    set(singlevalues TARGET YAML_FILE GENERATED_HEADER)
215    cmake_parse_arguments(ARG "" "${singlevalues}" "" ${ARGN})
216
217    if(NOT DEFINED ARG_YAML_FILE)
218        set(ARG_YAML_FILE ${CMAKE_CURRENT_SOURCE_DIR}/messages.yaml)
219    endif()
220
221    if(NOT DEFINED ARG_GENERATED_HEADER)
222        set(ARG_GENERATED_HEADER messages.h)
223    endif()
224
225    get_filename_component(YAML_FILE ${ARG_YAML_FILE} ABSOLUTE)
226
227    if(IS_ABSOLUTE ${ARG_GENERATED_HEADER})
228        get_filename_component(GENERATED_DIR ${ARG_GENERATED_HEADER} DIRECTORY)
229        set(MESSAGES_H ${ARG_GENERATED_HEADER})
230    else()
231        set(INCLUDE_DIR ${CMAKE_CURRENT_BINARY_DIR}/panda_gen_messages)
232        set(GENERATED_DIR ${INCLUDE_DIR}/generated)
233        set(MESSAGES_H ${GENERATED_DIR}/${ARG_GENERATED_HEADER})
234    endif()
235
236    file(MAKE_DIRECTORY ${GENERATED_DIR})
237    panda_gen_file(
238        DATA ${YAML_FILE}
239        TEMPLATE ${PANDA_ROOT}/templates/messages/messages.h.erb
240        OUTPUTFILE ${MESSAGES_H}
241        API ${PANDA_ROOT}/templates/messages.rb
242    )
243
244    # Add dependencies for a target
245    if (NOT DEFINED ARG_TARGET)
246        set(ARG_TARGET messages_gen_${PROJECT_NAME})
247        add_custom_target(${ARG_TARGET})
248    endif()
249
250    if (DEFINED INCLUDE_DIR)
251        panda_target_include_directories(${ARG_TARGET} PUBLIC ${INCLUDE_DIR})
252    endif()
253    add_custom_target(${ARG_TARGET}_messages DEPENDS ${MESSAGES_H})
254    add_dependencies(${ARG_TARGET} ${ARG_TARGET}_messages)
255    add_dependencies(panda_gen_files ${ARG_TARGET}_messages)
256endfunction()
257
258add_custom_target(plugin_options_gen)
259set_target_properties(plugin_options_gen PROPERTIES PLUGIN_OPTIONS_YAML_FILES "${PANDA_ROOT}/templates/plugin_options.yaml")
260
261add_custom_target(entrypoints_yaml_gen)
262set_target_properties(entrypoints_yaml_gen PROPERTIES ENTRYPOINT_YAML_FILES "${PANDA_ROOT}/runtime/entrypoints/entrypoints.yaml")
263
264add_custom_target(runtime_options_gen)
265set_target_properties(runtime_options_gen PROPERTIES RUNTIME_OPTIONS_YAML_FILES "${PANDA_ROOT}/runtime/options.yaml")
266
267add_custom_target(compiler_options_gen)
268set_target_properties(compiler_options_gen PROPERTIES COMPILER_OPTIONS_YAML_FILES "${PANDA_ROOT}/compiler/compiler.yaml")
269
270function(add_plugin_options YAML_FILE_PATH)
271    get_target_property(YAML_FILES plugin_options_gen PLUGIN_OPTIONS_YAML_FILES)
272    list(APPEND YAML_FILES ${YAML_FILE_PATH})
273    set_target_properties(plugin_options_gen PROPERTIES PLUGIN_OPTIONS_YAML_FILES "${YAML_FILES}")
274endfunction()
275
276function(add_entrypoints_yaml YAML_FILE_PATH)
277    get_target_property(YAML_FILES entrypoints_yaml_gen ENTRYPOINT_YAML_FILES)
278    list(APPEND YAML_FILES ${YAML_FILE_PATH})
279    set_target_properties(entrypoints_yaml_gen PROPERTIES ENTRYPOINT_YAML_FILES "${YAML_FILES}")
280endfunction()
281
282function(add_runtime_options YAML_FILE_PATH)
283    get_target_property(YAML_FILES runtime_options_gen RUNTIME_OPTIONS_YAML_FILES)
284    list(APPEND YAML_FILES ${YAML_FILE_PATH})
285    set_target_properties(runtime_options_gen PROPERTIES RUNTIME_OPTIONS_YAML_FILES "${YAML_FILES}")
286endfunction()
287
288function(add_compiler_options YAML_FILE_PATH)
289    get_target_property(YAML_FILES compiler_options_gen COMPILER_OPTIONS_YAML_FILES)
290    list(APPEND YAML_FILES ${YAML_FILE_PATH})
291    set_target_properties(compiler_options_gen PROPERTIES COMPILER_OPTIONS_YAML_FILES "${YAML_FILES}")
292endfunction()
293