blob: ec8279c2cba6f0b7dae3edd068a5014128b69bd2 [file] [log] [blame]
Gyorgy Szing5c873232019-05-10 23:28:14 +02001#-------------------------------------------------------------------------------
David Hud4ac5d12020-04-01 11:27:39 +08002# Copyright (c) 2019-2020, Arm Limited. All rights reserved.
Gyorgy Szing5c873232019-05-10 23:28:14 +02003#
4# SPDX-License-Identifier: BSD-3-Clause
5#
6#-------------------------------------------------------------------------------
7
8#A script to fill out the "toctree" file lists in index.rst.in to put design
9#documents into the correct section based on their state.
10#
11#First rst files are parsed under a defined directory, to identify document
12#status based on value of the ":Status:" field. Each state will have a list
13#being generated to which matching documents are added. These lists are used
14#then to fill template values using configure_file()
15#
David Hud4ac5d12020-04-01 11:27:39 +080016#The ":Status:" field is optional according to design proposal process.
17#Apparently, only the documents in "Accepted" status will be merged and included
18#in Sphinx build. Therefore, a design document without ":Status:" field will be
19#put in "Accepted" category by default.
20#If there are design document drafts in local environment, it is assumed that
21#developers are aware of the status of these drafts and won't be confused.
22#A message will be still thrown out when a design document doesn't contain
23#":Status:" field. It can be removed if more and more design documents don't
24#maintain that field.
25#
Gyorgy Szing5c873232019-05-10 23:28:14 +020026#Functions are used whenever possible to avoid global variable name space
27#pollution.
28#
29
30Include(CMakeParseArguments)
31
David Hud4ac5d12020-04-01 11:27:39 +080032#Set the status value here to avoid any typo or upper/lower case trouble.
33set(ACCEPTED_STATUS "ACCEPTED")
34set(DRAFT_STATUS "DRAFT")
35set(DETAILED_STATUS "DETAILED")
36#"NO_SET" is used to mark documents without status field.
37set(NO_SET "NO_SET")
38#"INVALID_STATUS" is used to mark a document which specifies the status but the
39#status value is invalid or unrecognized.
40set(INVALID_STATUS "INVALID_STATUS")
41
Gyorgy Szing5c873232019-05-10 23:28:14 +020042#This function will search for .rst files in a given directory, read them and
Galanakis, Minos0c1ad782019-11-08 11:28:40 +000043#check if the ":Status:" field is defined in them. Then will add each file to a
Gyorgy Szing5c873232019-05-10 23:28:14 +020044#list with a name matching the status value.
45#See the definition of _STATE_VALUES below for a list of valid state values.
David Hud4ac5d12020-04-01 11:27:39 +080046#Files without state value will be placed on the both "Accepted" list and
47#"NO_SET" list.
Gyorgy Szing5c873232019-05-10 23:28:14 +020048#State value comparison is case insensitive.
49#
50#The output lists will have the prefix specified in the PREFIX parameter.
51#
52#Inputs:
53# DIR Directory to scan for rst files.
54# PREFIX The prefix of output list variables.
55#
56#Outputs:
David Hud4ac5d12020-04-01 11:27:39 +080057# <prefix>_<state> - list; all files with a valid state value.
58# <prefix>_NO_SET - list; all files without status field.
59# <prefix>_INVALID_STATUS - list; all files with invalid status field.
60#
Gyorgy Szing5c873232019-05-10 23:28:14 +020061#Examples
62# sphinx_categorize_rst(DIR ${TFM_ROOT_DIR}/docs/design_documents
63# PREFIX "DESIGN_DOCS")
64#
65function(sphinx_categorize_rst)
David Hud4ac5d12020-04-01 11:27:39 +080066 #Valid state values.
67 set(_STATE_VALUES ${DRAFT_STATUS} ${ACCEPTED_STATUS} ${DETAILED_STATUS}
68 ${NO_SET} ${INVALID_STATUS})
Gyorgy Szing5c873232019-05-10 23:28:14 +020069
70 #No option (on/off) arguments
71 set( _OPTIONS_ARGS )
72 #Single option arguments (e.g. PROJ_NAME "bubu_project")
73 set( _ONE_VALUE_ARGS DIR PREFIX)
74 #List arguments (e.g. LANGUAGES C ASM CXX)
75 set( _MULTI_VALUE_ARGS )
76
77 cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}"
78 "${_MULTI_VALUE_ARGS}" ${ARGN} )
79
80 #Check parameters
81 foreach(_PARAM IN LISTS _ONE_VALUE_ARGS)
82 if (NOT DEFINED _MY_PARAMS_${_PARAM})
83 message(FATAL_ERROR "Parameter ${_PARAM} is missing!")
84 endif()
85 endforeach()
86
87 #Search for .rst files
88 file(GLOB_RECURSE _RST_FILES
89 LIST_DIRECTORIES False
90 ${_MY_PARAMS_DIR}/**.rst)
91
92 #Loop over .rst files
93 foreach(_FILE IN LISTS _RST_FILES)
94 #Read the file and return the first status line.
95 file(STRINGS ${_FILE} _CONTENT REGEX ":Status:" LIMIT_COUNT 1)
96
97 #Nothing read -> the field is missing
98 if (_CONTENT STREQUAL "")
David Hud4ac5d12020-04-01 11:27:39 +080099 #If a document doesn't maintain a status field, put it in
100 #Accepted list by default.
101 list(APPEND _STATUS_${ACCEPTED_STATUS} ${_FILE})
102 #Also add the file to the "NO_SET" list. Thus it can be
103 #highlighted later.
104 list(APPEND _STATUS_${NO_SET} ${_FILE})
Gyorgy Szing5c873232019-05-10 23:28:14 +0200105 else()
106 #convert to upper case for case insensitive matching.
107 string(TOUPPER ${_CONTENT} _CONTENT)
108
109 #loop over status values
110 foreach(_STATUS IN LISTS _STATE_VALUES)
111 #convert to upper case for case insensitive matching.
112 string(TOUPPER ${_STATUS} _STATUS)
113 #does status match the value from the file?
114 if (_CONTENT MATCHES ":STATUS:[ ]*${_STATUS}")
115 #add it to the list
116 list(APPEND _STATUS_${_STATUS} ${_FILE})
117 #and exit the loop
118 break()
119 endif()
David Hud4ac5d12020-04-01 11:27:39 +0800120
121 #If the status value is invalid.
122 if (_STATUS STREQUAL ${INVALID_STATUS})
123 list(APPEND _STATUS_${INVALID_STATUS} ${_FILE})
Gyorgy Szing5c873232019-05-10 23:28:14 +0200124 endif()
125 endforeach()
126 endif()
127 endforeach()
128
129 #return the lists to the caller
130 foreach(_STATUS IN LISTS _STATE_VALUES)
131 string(TOUPPER ${_STATUS} _STATUS)
132
133 if (DEFINED _STATUS_${_STATUS})
134 set(${_MY_PARAMS_PREFIX}_${_STATUS} ${_STATUS_${_STATUS}}
135 PARENT_SCOPE)
136 endif()
137 endforeach()
138endfunction()
139
140#Configure (fill in) the Sphinx index.rst.in template file.
141#Call sphinx_categorize_rst() to get the .rst files sorted to lists, and then
142#create the list of files for each design document section (convert the CMake
143#lists to properly formatted text).
144#Finally call configure_file() to fill in the values.
145#
146#Inputs:
147# SRC Full path to template index file
148# DST Full patch to configured output file.
David Hud4ac5d12020-04-01 11:27:39 +0800149# DOC_DIR Path to design documents directory.
Gyorgy Szing5c873232019-05-10 23:28:14 +0200150# DOC_ROOT Path to root directory of documentation
151#
152#Outputs:
153# Configured <DST> file.
154#
155#Examples
156# sphinx_categorize_rst(DIR ${TFM_ROOT_DIR}/docs/design_documents
157# PREFIX "DESIGN_DOCS")
158#
159function(sphinx_configure_index)
David Hud4ac5d12020-04-01 11:27:39 +0800160 set(_STATE_VALUES ${DRAFT_STATUS} ${ACCEPTED_STATUS} ${DETAILED_STATUS}
161 ${DEFAULT_STATUS} ${INVALID_STATUS})
Gyorgy Szing5c873232019-05-10 23:28:14 +0200162
163 #No option (on/off) arguments
164 set( _OPTIONS_ARGS )
165 #Single option arguments (e.g. PROJ_NAME "bubu_project")
166 set( _ONE_VALUE_ARGS SRC DST DOC_ROOT DOC_DIR)
167 #List arguments (e.g. LANGUAGES C ASM CXX)
168 set( _MULTI_VALUE_ARGS )
169
170 cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}"
171 "${_MULTI_VALUE_ARGS}" ${ARGN} )
172
173 #Check parameters
174 foreach(_PARAM IN LISTS _ONE_VALUE_ARGS)
175 if (NOT DEFINED _MY_PARAMS_${_PARAM})
176 message(FATAL_ERROR "Parameter ${_PARAM} is missing!")
177 endif()
178 endforeach()
179
180 #Assign design documents to lists based on their status
181 sphinx_categorize_rst(DIR ${_MY_PARAMS_DOC_DIR} PREFIX "_DD")
182
David Hud4ac5d12020-04-01 11:27:39 +0800183 #Highlight documents without status field
184 if (DEFINED _DD_${NO_SET})
185 string(REPLACE ";" "\n \t" _DD_${NO_SET} "${_DD_${NO_SET}}")
186 message(" The following documents are put into Accepted category without status field:\n \t${_DD_${NO_SET}}")
187 endif()
188
Gyorgy Szing5c873232019-05-10 23:28:14 +0200189 #Look for invalid documents
David Hud4ac5d12020-04-01 11:27:39 +0800190 if (DEFINED _DD_${INVALID_STATUS})
191 string(REPLACE ";" "\n \t" _DD_${INVALID_STATUS} "${_DD_${INVALID_STATUS}}")
192 message(WARNING " The following documents provide invalid status information:\n \t${_DD_${INVALID_STATUS}}")
Gyorgy Szing5c873232019-05-10 23:28:14 +0200193 endif()
194
195 #The document root must be an absolute path
196 get_filename_component(_MY_PARAMS_DOC_ROOT "${_MY_PARAMS_DOC_ROOT}"
197 ABSOLUTE)
198
199 #Loop over status lists
David Hud4ac5d12020-04-01 11:27:39 +0800200 foreach(_STATUS IN ITEMS ${DRAFT_STATUS} ${DETAILED_STATUS} ${ACCEPTED_STATUS})
Gyorgy Szing5c873232019-05-10 23:28:14 +0200201 #Create an empty file list for this status
202 set(${_STATUS}_DD_LIST "")
203 #If the source list is empty go to next iteration
204 if (NOT DEFINED _DD_${_STATUS})
205 continue()
206 endif()
207
208 #Loop over files on the list of this status
209 foreach(_FILE IN LISTS _DD_${_STATUS})
Galanakis, Minos0c1ad782019-11-08 11:28:40 +0000210
211 # Strip path from the filesince index is placed in same location
212 get_filename_component(_FILE ${_FILE} NAME)
Gyorgy Szing5c873232019-05-10 23:28:14 +0200213 #Detailed and Draft files go to the same section
David Hud4ac5d12020-04-01 11:27:39 +0800214 if (_STATUS STREQUAL ${DETAILED_STATUS})
215 set(_STATUS ${DRAFT_STATUS})
Gyorgy Szing5c873232019-05-10 23:28:14 +0200216 endif()
217
218 #Append the file to the output string
Galanakis, Minos0c1ad782019-11-08 11:28:40 +0000219 string(APPEND ${_STATUS}_DD_LIST "\n ${_FILE}")
Gyorgy Szing5c873232019-05-10 23:28:14 +0200220 endforeach()
221 endforeach()
222
223 #Call configure file to fill out the template.
224 configure_file(${_MY_PARAMS_SRC} ${_MY_PARAMS_DST} @ONLY)
225endfunction()
226
227#If being run in script mode (cmake -P) and not included.
228if (DEFINED CMAKE_SCRIPT_MODE_FILE
229 AND (CMAKE_CURRENT_LIST_FILE STREQUAL CMAKE_SCRIPT_MODE_FILE))
230 #Check input variables.
231 foreach(_PARAM IN ITEMS SPHINX_TEMPLATE_INDEX_FILE SPHINX_CONFIGURED_INDEX_FILE
232 SPHINX_DESIGN_DOC_ROOT TFM_ROOT_DIR)
233 if (NOT DEFINED ${_PARAM})
234 message(FATAL_ERROR "Parameter ${_PARAM} is not set!")
235 endif()
236 endforeach()
237
238 sphinx_configure_index(SRC ${SPHINX_TEMPLATE_INDEX_FILE}
239 DST ${SPHINX_CONFIGURED_INDEX_FILE}
240 DOC_DIR ${SPHINX_DESIGN_DOC_ROOT}
241 DOC_ROOT ${TFM_ROOT_DIR})
242endif()