blob: e76c448a6c277b5bbef6e557f7e9305fb3091419 [file] [log] [blame]
Gyorgy Szing5c873232019-05-10 23:28:14 +02001#-------------------------------------------------------------------------------
2# Copyright (c) 2019, Arm Limited. All rights reserved.
3#
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#
16#Functions are used whenever possible to avoid global variable name space
17#pollution.
18#
19
20Include(CMakeParseArguments)
21
22#This function will search for .rst files in a given directory, read them and
23#check if the “:Status:” field is defined in them. Then will add each file to a
24#list with a name matching the status value.
25#See the definition of _STATE_VALUES below for a list of valid state values.
26#Files with missing or invalid state value will be placed on the "unknown" list.
27#State value comparison is case insensitive.
28#
29#The output lists will have the prefix specified in the PREFIX parameter.
30#
31#Inputs:
32# DIR Directory to scan for rst files.
33# PREFIX The prefix of output list variables.
34#
35#Outputs:
36# <prefix>_<state> - list; will hold all files with a valid state value.
37# <prefix>_unknown - list; all files with missing or invalid state
38# value.
39#Examples
40# sphinx_categorize_rst(DIR ${TFM_ROOT_DIR}/docs/design_documents
41# PREFIX "DESIGN_DOCS")
42#
43function(sphinx_categorize_rst)
44 #Valid state values. "unknown" is used as a quard to detect invalid status
45 #values.
46 set(_STATE_VALUES "draft" "rejected" "accepted" "detailed" "unknown")
47
48 #No option (on/off) arguments
49 set( _OPTIONS_ARGS )
50 #Single option arguments (e.g. PROJ_NAME "bubu_project")
51 set( _ONE_VALUE_ARGS DIR PREFIX)
52 #List arguments (e.g. LANGUAGES C ASM CXX)
53 set( _MULTI_VALUE_ARGS )
54
55 cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}"
56 "${_MULTI_VALUE_ARGS}" ${ARGN} )
57
58 #Check parameters
59 foreach(_PARAM IN LISTS _ONE_VALUE_ARGS)
60 if (NOT DEFINED _MY_PARAMS_${_PARAM})
61 message(FATAL_ERROR "Parameter ${_PARAM} is missing!")
62 endif()
63 endforeach()
64
65 #Search for .rst files
66 file(GLOB_RECURSE _RST_FILES
67 LIST_DIRECTORIES False
68 ${_MY_PARAMS_DIR}/**.rst)
69
70 #Loop over .rst files
71 foreach(_FILE IN LISTS _RST_FILES)
72 #Read the file and return the first status line.
73 file(STRINGS ${_FILE} _CONTENT REGEX ":Status:" LIMIT_COUNT 1)
74
75 #Nothing read -> the field is missing
76 if (_CONTENT STREQUAL "")
77 list(APPEND _STATUS_UNKNOWN ${_FILE})
78 else()
79 #convert to upper case for case insensitive matching.
80 string(TOUPPER ${_CONTENT} _CONTENT)
81
82 #loop over status values
83 foreach(_STATUS IN LISTS _STATE_VALUES)
84 #convert to upper case for case insensitive matching.
85 string(TOUPPER ${_STATUS} _STATUS)
86 #does status match the value from the file?
87 if (_CONTENT MATCHES ":STATUS:[ ]*${_STATUS}")
88 #add it to the list
89 list(APPEND _STATUS_${_STATUS} ${_FILE})
90 #and exit the loop
91 break()
92 endif()
93 #"unknown" status is used as a quard and is an invalid value.
94 #If we reach it the file has invalid status value.
95 if (_STATUS STREQUAL "UNKNOWN")
96 #add the file to the unknown list
97 list(APPEND _STATUS_${_STATUS} ${_FILE})
98 endif()
99 endforeach()
100 endif()
101 endforeach()
102
103 #return the lists to the caller
104 foreach(_STATUS IN LISTS _STATE_VALUES)
105 string(TOUPPER ${_STATUS} _STATUS)
106
107 if (DEFINED _STATUS_${_STATUS})
108 set(${_MY_PARAMS_PREFIX}_${_STATUS} ${_STATUS_${_STATUS}}
109 PARENT_SCOPE)
110 endif()
111 endforeach()
112endfunction()
113
114#Configure (fill in) the Sphinx index.rst.in template file.
115#Call sphinx_categorize_rst() to get the .rst files sorted to lists, and then
116#create the list of files for each design document section (convert the CMake
117#lists to properly formatted text).
118#Finally call configure_file() to fill in the values.
119#
120#Inputs:
121# SRC Full path to template index file
122# DST Full patch to configured output file.
123#....DOC_DIR Path to design documents directory.
124# DOC_ROOT Path to root directory of documentation
125#
126#Outputs:
127# Configured <DST> file.
128#
129#Examples
130# sphinx_categorize_rst(DIR ${TFM_ROOT_DIR}/docs/design_documents
131# PREFIX "DESIGN_DOCS")
132#
133function(sphinx_configure_index)
134 set(_STATE_VALUES "draft" "rejected" "accepted" "detailed" "unknown")
135
136 #No option (on/off) arguments
137 set( _OPTIONS_ARGS )
138 #Single option arguments (e.g. PROJ_NAME "bubu_project")
139 set( _ONE_VALUE_ARGS SRC DST DOC_ROOT DOC_DIR)
140 #List arguments (e.g. LANGUAGES C ASM CXX)
141 set( _MULTI_VALUE_ARGS )
142
143 cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}"
144 "${_MULTI_VALUE_ARGS}" ${ARGN} )
145
146 #Check parameters
147 foreach(_PARAM IN LISTS _ONE_VALUE_ARGS)
148 if (NOT DEFINED _MY_PARAMS_${_PARAM})
149 message(FATAL_ERROR "Parameter ${_PARAM} is missing!")
150 endif()
151 endforeach()
152
153 #Assign design documents to lists based on their status
154 sphinx_categorize_rst(DIR ${_MY_PARAMS_DOC_DIR} PREFIX "_DD")
155
156 #Look for invalid documents
157 if (DEFINED _DD_UNKNOWN)
158 string(REPLACE ";" "\n \t" _DD_UNKNOWN "${_DD_UNKNOWN}")
159 message(FATAL_ERROR " The following documents have no or invalid status:\n \t${_DD_UNKNOWN}")
160 endif()
161
162 #The document root must be an absolute path
163 get_filename_component(_MY_PARAMS_DOC_ROOT "${_MY_PARAMS_DOC_ROOT}"
164 ABSOLUTE)
165
166 #Loop over status lists
167 foreach(_STATUS IN ITEMS "DRAFT" "DETAILED" "ACCEPTED" "REJECTED")
168 #Create an empty file list for this status
169 set(${_STATUS}_DD_LIST "")
170 #If the source list is empty go to next iteration
171 if (NOT DEFINED _DD_${_STATUS})
172 continue()
173 endif()
174
175 #Loop over files on the list of this status
176 foreach(_FILE IN LISTS _DD_${_STATUS})
177 #Get the path of the file relative to the document root
178 file(RELATIVE_PATH _REL_FILE ${_MY_PARAMS_DOC_ROOT} ${_FILE})
179 #Detailed and Draft files go to the same section
180 if (_STATUS STREQUAL "DETAILED")
181 set(_STATUS "DRAFT")
182 endif()
183
184 #Append the file to the output string
185 string(APPEND ${_STATUS}_DD_LIST "\n ${_REL_FILE}")
186 endforeach()
187 endforeach()
188
189 #Call configure file to fill out the template.
190 configure_file(${_MY_PARAMS_SRC} ${_MY_PARAMS_DST} @ONLY)
191endfunction()
192
193#If being run in script mode (cmake -P) and not included.
194if (DEFINED CMAKE_SCRIPT_MODE_FILE
195 AND (CMAKE_CURRENT_LIST_FILE STREQUAL CMAKE_SCRIPT_MODE_FILE))
196 #Check input variables.
197 foreach(_PARAM IN ITEMS SPHINX_TEMPLATE_INDEX_FILE SPHINX_CONFIGURED_INDEX_FILE
198 SPHINX_DESIGN_DOC_ROOT TFM_ROOT_DIR)
199 if (NOT DEFINED ${_PARAM})
200 message(FATAL_ERROR "Parameter ${_PARAM} is not set!")
201 endif()
202 endforeach()
203
204 sphinx_configure_index(SRC ${SPHINX_TEMPLATE_INDEX_FILE}
205 DST ${SPHINX_CONFIGURED_INDEX_FILE}
206 DOC_DIR ${SPHINX_DESIGN_DOC_ROOT}
207 DOC_ROOT ${TFM_ROOT_DIR})
208endif()