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