aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGyorgy Szing <Gyorgy.Szing@arm.com>2019-05-10 23:28:14 +0200
committerGyörgy Szing <gyorgy.szing@arm.com>2019-07-01 08:02:08 +0000
commit5c87323db941c3470eb4d4998981ced8b33cf84c (patch)
tree7b4ea7790bc896b82295c1ad794aa8afb4e8db0d
parentfeb0f0c7e42ab0f9f2e5fc0e855267c96a9b8175 (diff)
downloadtrusted-firmware-m-5c87323db941c3470eb4d4998981ced8b33cf84c.tar.gz
Doc: add design proposal process documentation.
Add new document section for processes and new document describing the design proposal process. Added CMake support for status handling of design documents. Improved update process (dependency handling) of Sphinx documentation. Fixed issue where the intermediate document files from the build directory were added to Sphinx output if the build directory was placed under TF-M root directory. Change-Id: Ie21abe120ffcb5f0a79ddf1c398eb198959878f3 Signed-off-by: Gyorgy Szing <Gyorgy.Szing@arm.com>
-rw-r--r--cmake/Common/BuildSphinxDoc.cmake30
-rw-r--r--cmake/SphinxCopyDoc.cmake14
-rw-r--r--cmake/SphinxDesignDocStatus.cmake208
-rw-r--r--docs/index.rst.in (renamed from docs/index.rst)19
-rw-r--r--docs/processes/tfm_design_proposal_process.rst151
5 files changed, 409 insertions, 13 deletions
diff --git a/cmake/Common/BuildSphinxDoc.cmake b/cmake/Common/BuildSphinxDoc.cmake
index 68887ff217..997de3b9c7 100644
--- a/cmake/Common/BuildSphinxDoc.cmake
+++ b/cmake/Common/BuildSphinxDoc.cmake
@@ -78,6 +78,9 @@ if (NOT SPHINX_NODOC)
set(SPHINXCFG_TEMPLATE_FILE "${TFM_ROOT_DIR}/docs/conf.py.in")
set(SPHINXCFG_CONFIGURED_FILE "${SPHINXCFG_OUTPUT_PATH}/conf.py")
+ set(SPHINX_TEMPLATE_INDEX_FILE "${TFM_ROOT_DIR}/docs/index.rst.in")
+ set(SPHINX_CONFIGURED_INDEX_FILE "${SPHINX_TMP_DOC_DIR}/index.rst")
+ set(SPHINX_DESIGN_DOC_ROOT "${TFM_ROOT_DIR}/docs/design_documents")
#Version ID of TF-M.
#TODO: this shall not be hard-coded here. We need a process to define the
@@ -85,11 +88,34 @@ if (NOT SPHINX_NODOC)
set(SPHINXCFG_TFM_VERSION "1.0.0-Beta")
set(SPHINXCFG_TFM_VERSION_FULL "Version 1.0.0-Beta")
+ get_filename_component(_NDX_FILE_DIR ${SPHINX_CONFIGURED_INDEX_FILE} DIRECTORY )
+
+ #This command does not generates the specifyed output file and thus it will
+ #allways be run. Any other command or target depending on the "run-allways"
+ #output will be alwways executed too.
+ add_custom_command(OUTPUT run-allways
+ COMMAND "${CMAKE_COMMAND}" -E echo)
+
#Using add_custom_command allows CMake to generate proper clean commands
#for document generation.
add_custom_command(OUTPUT "${SPHINX_TMP_DOC_DIR}"
- COMMAND "${CMAKE_COMMAND}" -D TFM_ROOT_DIR=${TFM_ROOT_DIR} -D DST_DIR=${SPHINX_TMP_DOC_DIR} -P "${TFM_ROOT_DIR}/cmake/SphinxCopyDoc.cmake"
+ "${SPHINX_CONFIGURED_INDEX_FILE}"
+ #Create target directory for SPHINX_CONFIGURED_INDEX_FILE. Needed
+ #by the next command.
+ COMMAND "${CMAKE_COMMAND}" -E make_directory "${_NDX_FILE_DIR}"
+ #Fill out index.rst template
+ COMMAND "${CMAKE_COMMAND}" -D TFM_ROOT_DIR=${TFM_ROOT_DIR}
+ -D SPHINX_TEMPLATE_INDEX_FILE=${SPHINX_TEMPLATE_INDEX_FILE}
+ -D SPHINX_CONFIGURED_INDEX_FILE=${SPHINX_CONFIGURED_INDEX_FILE}
+ -D SPHINX_DESIGN_DOC_ROOT=${SPHINX_DESIGN_DOC_ROOT}
+ -P "${TFM_ROOT_DIR}/cmake/SphinxDesignDocStatus.cmake"
+ #Copy document files to temp direcotry
+ COMMAND "${CMAKE_COMMAND}" -D TFM_ROOT_DIR=${TFM_ROOT_DIR}
+ -D DST_DIR=${SPHINX_TMP_DOC_DIR}
+ -D BINARY_DIR=${CMAKE_BINARY_DIR}
+ -P "${TFM_ROOT_DIR}/cmake/SphinxCopyDoc.cmake"
WORKING_DIRECTORY "${TFM_ROOT_DIR}"
+ DEPENDS run-allways
VERBATIM
)
@@ -100,7 +126,7 @@ if (NOT SPHINX_NODOC)
add_custom_command(OUTPUT "${SPHINXCFG_OUTPUT_PATH}/html"
COMMAND "${SPHINX_EXECUTABLE}" -c "${SPHINXCFG_OUTPUT_PATH}" -b html "${SPHINX_TMP_DOC_DIR}" "${SPHINXCFG_OUTPUT_PATH}/html"
WORKING_DIRECTORY "${TFM_ROOT_DIR}"
- DEPENDS create_sphinx_input
+ DEPENDS create_sphinx_input run-allways
COMMENT "Running Sphinx to generate user guide (HTML)."
VERBATIM
)
diff --git a/cmake/SphinxCopyDoc.cmake b/cmake/SphinxCopyDoc.cmake
index 0dc1b71327..e95757c739 100644
--- a/cmake/SphinxCopyDoc.cmake
+++ b/cmake/SphinxCopyDoc.cmake
@@ -26,10 +26,10 @@
#
#Usage:
# cmake -DDST_DIR=<path to destination> -DTFM_ROOT_DIR=<path to tf-m root> \
-# -P SphinxCopyDoc.cmake
+# -DBINARY_DIR=${CMAKE_BINARY_DIR} -P SphinxCopyDoc.cmake
#Check input parameters
-foreach(_PARAM IN ITEMS TFM_ROOT_DIR DST_DIR)
+foreach(_PARAM IN ITEMS TFM_ROOT_DIR DST_DIR BINARY_DIR)
if (NOT DEFINED ${_PARAM})
message(FATAL_ERROR "Variable ${_PARAM} is undefined. Please add -D${_PARAM}=<...> when calling this script.")
endif()
@@ -47,14 +47,14 @@ file(GLOB_RECURSE _COPY_FILES
"${TFM_ROOT_DIR}/*.jpg"
"${TFM_ROOT_DIR}/dco.txt")
-#Subtract exluded files from copy files
-list(REMOVE_ITEM _COPY_FILES "docs/index.rst")
+#Remove intermediate and final document build outputs.
+foreach(_PATH IN ITEMS BINARY_DIR DST_DIR)
+ file(RELATIVE_PATH _REL_DIR ${TFM_ROOT_DIR} ${${_PATH}})
+ list(FILTER _COPY_FILES EXCLUDE REGEX "${_REL_DIR}/.*")
+endforeach()
#Copy files with directory tree.
foreach(_FILE ${_COPY_FILES})
get_filename_component(_DIR ${_FILE} DIRECTORY)
file(COPY ${_FILE} DESTINATION "${DST_DIR}/${_DIR}")
endforeach()
-
-#Copy index.rst to the top level
-file(COPY "${TFM_ROOT_DIR}/docs/index.rst" DESTINATION "${DST_DIR}")
diff --git a/cmake/SphinxDesignDocStatus.cmake b/cmake/SphinxDesignDocStatus.cmake
new file mode 100644
index 0000000000..e76c448a6c
--- /dev/null
+++ b/cmake/SphinxDesignDocStatus.cmake
@@ -0,0 +1,208 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2019, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+#A script to fill out the "toctree" file lists in index.rst.in to put design
+#documents into the correct section based on their state.
+#
+#First rst files are parsed under a defined directory, to identify document
+#status based on value of the ":Status:" field. Each state will have a list
+#being generated to which matching documents are added. These lists are used
+#then to fill template values using configure_file()
+#
+#Functions are used whenever possible to avoid global variable name space
+#pollution.
+#
+
+Include(CMakeParseArguments)
+
+#This function will search for .rst files in a given directory, read them and
+#check if the “:Status:” field is defined in them. Then will add each file to a
+#list with a name matching the status value.
+#See the definition of _STATE_VALUES below for a list of valid state values.
+#Files with missing or invalid state value will be placed on the "unknown" list.
+#State value comparison is case insensitive.
+#
+#The output lists will have the prefix specified in the PREFIX parameter.
+#
+#Inputs:
+# DIR Directory to scan for rst files.
+# PREFIX The prefix of output list variables.
+#
+#Outputs:
+# <prefix>_<state> - list; will hold all files with a valid state value.
+# <prefix>_unknown - list; all files with missing or invalid state
+# value.
+#Examples
+# sphinx_categorize_rst(DIR ${TFM_ROOT_DIR}/docs/design_documents
+# PREFIX "DESIGN_DOCS")
+#
+function(sphinx_categorize_rst)
+ #Valid state values. "unknown" is used as a quard to detect invalid status
+ #values.
+ set(_STATE_VALUES "draft" "rejected" "accepted" "detailed" "unknown")
+
+ #No option (on/off) arguments
+ set( _OPTIONS_ARGS )
+ #Single option arguments (e.g. PROJ_NAME "bubu_project")
+ set( _ONE_VALUE_ARGS DIR PREFIX)
+ #List arguments (e.g. LANGUAGES C ASM CXX)
+ set( _MULTI_VALUE_ARGS )
+
+ cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}"
+ "${_MULTI_VALUE_ARGS}" ${ARGN} )
+
+ #Check parameters
+ foreach(_PARAM IN LISTS _ONE_VALUE_ARGS)
+ if (NOT DEFINED _MY_PARAMS_${_PARAM})
+ message(FATAL_ERROR "Parameter ${_PARAM} is missing!")
+ endif()
+ endforeach()
+
+ #Search for .rst files
+ file(GLOB_RECURSE _RST_FILES
+ LIST_DIRECTORIES False
+ ${_MY_PARAMS_DIR}/**.rst)
+
+ #Loop over .rst files
+ foreach(_FILE IN LISTS _RST_FILES)
+ #Read the file and return the first status line.
+ file(STRINGS ${_FILE} _CONTENT REGEX ":Status:" LIMIT_COUNT 1)
+
+ #Nothing read -> the field is missing
+ if (_CONTENT STREQUAL "")
+ list(APPEND _STATUS_UNKNOWN ${_FILE})
+ else()
+ #convert to upper case for case insensitive matching.
+ string(TOUPPER ${_CONTENT} _CONTENT)
+
+ #loop over status values
+ foreach(_STATUS IN LISTS _STATE_VALUES)
+ #convert to upper case for case insensitive matching.
+ string(TOUPPER ${_STATUS} _STATUS)
+ #does status match the value from the file?
+ if (_CONTENT MATCHES ":STATUS:[ ]*${_STATUS}")
+ #add it to the list
+ list(APPEND _STATUS_${_STATUS} ${_FILE})
+ #and exit the loop
+ break()
+ endif()
+ #"unknown" status is used as a quard and is an invalid value.
+ #If we reach it the file has invalid status value.
+ if (_STATUS STREQUAL "UNKNOWN")
+ #add the file to the unknown list
+ list(APPEND _STATUS_${_STATUS} ${_FILE})
+ endif()
+ endforeach()
+ endif()
+ endforeach()
+
+ #return the lists to the caller
+ foreach(_STATUS IN LISTS _STATE_VALUES)
+ string(TOUPPER ${_STATUS} _STATUS)
+
+ if (DEFINED _STATUS_${_STATUS})
+ set(${_MY_PARAMS_PREFIX}_${_STATUS} ${_STATUS_${_STATUS}}
+ PARENT_SCOPE)
+ endif()
+ endforeach()
+endfunction()
+
+#Configure (fill in) the Sphinx index.rst.in template file.
+#Call sphinx_categorize_rst() to get the .rst files sorted to lists, and then
+#create the list of files for each design document section (convert the CMake
+#lists to properly formatted text).
+#Finally call configure_file() to fill in the values.
+#
+#Inputs:
+# SRC Full path to template index file
+# DST Full patch to configured output file.
+#....DOC_DIR Path to design documents directory.
+# DOC_ROOT Path to root directory of documentation
+#
+#Outputs:
+# Configured <DST> file.
+#
+#Examples
+# sphinx_categorize_rst(DIR ${TFM_ROOT_DIR}/docs/design_documents
+# PREFIX "DESIGN_DOCS")
+#
+function(sphinx_configure_index)
+ set(_STATE_VALUES "draft" "rejected" "accepted" "detailed" "unknown")
+
+ #No option (on/off) arguments
+ set( _OPTIONS_ARGS )
+ #Single option arguments (e.g. PROJ_NAME "bubu_project")
+ set( _ONE_VALUE_ARGS SRC DST DOC_ROOT DOC_DIR)
+ #List arguments (e.g. LANGUAGES C ASM CXX)
+ set( _MULTI_VALUE_ARGS )
+
+ cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}"
+ "${_MULTI_VALUE_ARGS}" ${ARGN} )
+
+ #Check parameters
+ foreach(_PARAM IN LISTS _ONE_VALUE_ARGS)
+ if (NOT DEFINED _MY_PARAMS_${_PARAM})
+ message(FATAL_ERROR "Parameter ${_PARAM} is missing!")
+ endif()
+ endforeach()
+
+ #Assign design documents to lists based on their status
+ sphinx_categorize_rst(DIR ${_MY_PARAMS_DOC_DIR} PREFIX "_DD")
+
+ #Look for invalid documents
+ if (DEFINED _DD_UNKNOWN)
+ string(REPLACE ";" "\n \t" _DD_UNKNOWN "${_DD_UNKNOWN}")
+ message(FATAL_ERROR " The following documents have no or invalid status:\n \t${_DD_UNKNOWN}")
+ endif()
+
+ #The document root must be an absolute path
+ get_filename_component(_MY_PARAMS_DOC_ROOT "${_MY_PARAMS_DOC_ROOT}"
+ ABSOLUTE)
+
+ #Loop over status lists
+ foreach(_STATUS IN ITEMS "DRAFT" "DETAILED" "ACCEPTED" "REJECTED")
+ #Create an empty file list for this status
+ set(${_STATUS}_DD_LIST "")
+ #If the source list is empty go to next iteration
+ if (NOT DEFINED _DD_${_STATUS})
+ continue()
+ endif()
+
+ #Loop over files on the list of this status
+ foreach(_FILE IN LISTS _DD_${_STATUS})
+ #Get the path of the file relative to the document root
+ file(RELATIVE_PATH _REL_FILE ${_MY_PARAMS_DOC_ROOT} ${_FILE})
+ #Detailed and Draft files go to the same section
+ if (_STATUS STREQUAL "DETAILED")
+ set(_STATUS "DRAFT")
+ endif()
+
+ #Append the file to the output string
+ string(APPEND ${_STATUS}_DD_LIST "\n ${_REL_FILE}")
+ endforeach()
+ endforeach()
+
+ #Call configure file to fill out the template.
+ configure_file(${_MY_PARAMS_SRC} ${_MY_PARAMS_DST} @ONLY)
+endfunction()
+
+#If being run in script mode (cmake -P) and not included.
+if (DEFINED CMAKE_SCRIPT_MODE_FILE
+ AND (CMAKE_CURRENT_LIST_FILE STREQUAL CMAKE_SCRIPT_MODE_FILE))
+ #Check input variables.
+ foreach(_PARAM IN ITEMS SPHINX_TEMPLATE_INDEX_FILE SPHINX_CONFIGURED_INDEX_FILE
+ SPHINX_DESIGN_DOC_ROOT TFM_ROOT_DIR)
+ if (NOT DEFINED ${_PARAM})
+ message(FATAL_ERROR "Parameter ${_PARAM} is not set!")
+ endif()
+ endforeach()
+
+ sphinx_configure_index(SRC ${SPHINX_TEMPLATE_INDEX_FILE}
+ DST ${SPHINX_CONFIGURED_INDEX_FILE}
+ DOC_DIR ${SPHINX_DESIGN_DOC_ROOT}
+ DOC_ROOT ${TFM_ROOT_DIR})
+endif()
diff --git a/docs/index.rst b/docs/index.rst.in
index f9c1282979..e2151a468a 100644
--- a/docs/index.rst
+++ b/docs/index.rst.in
@@ -3,8 +3,11 @@
..
The build-system will copy all documents into a temporary directory tree
before the documentation is built.
- This fill will be copied to the top level and thus please use relative paths
+ This file will be copied to the top level and thus please use relative paths
as if this file would be in <TFM_ROOT_DIR>.
+
+ The values between @ characters will be filled in by CMake.
+
Welcome to TF-M's documentation!
================================
@@ -29,6 +32,14 @@ Welcome to TF-M's documentation!
.. toctree::
:maxdepth: 2
+ :caption: Processes
+ :glob:
+ :hidden:
+
+ docs/processes/**
+
+.. toctree::
+ :maxdepth: 2
:caption: Secure services
:glob:
:hidden:
@@ -57,7 +68,7 @@ Welcome to TF-M's documentation!
:glob:
:hidden:
- docs/design_documents/*
+ @ACCEPTED_DD_LIST@
.. toctree::
:caption: Draft design documents
@@ -65,7 +76,7 @@ Welcome to TF-M's documentation!
:glob:
:hidden:
- docs/design_documents/drafts/*
+ @DRAFT_DD_LIST@
.. toctree::
:caption: Rejected design documents
@@ -73,7 +84,7 @@ Welcome to TF-M's documentation!
:glob:
:hidden:
- docs/design_documents/rejected/*
+ @REJECTED_DD_LIST@
.. include:: readme.rst
diff --git a/docs/processes/tfm_design_proposal_process.rst b/docs/processes/tfm_design_proposal_process.rst
new file mode 100644
index 0000000000..478220e0b4
--- /dev/null
+++ b/docs/processes/tfm_design_proposal_process.rst
@@ -0,0 +1,151 @@
+Design proposal process
+=======================
+
+:Author: Gyorgy Szing
+:Organisation: Arm Limited
+:Contact: Gyorgy Szing <gyorgy.szing@arm.com>
+
+Purpose and Content
+-------------------
+This document describes the steps of changing Trusted Firmware design. It
+specifies:
+
+ - the documentation format to be used
+ - the information which shall be captured
+ - the steps of the process
+ - and the location where the information shall be captured during the process.
+
+General
+-------
+The Trusted Firmware project uses the
+`reStructuredText <http://docutils.sourceforge.net/rst.html>`_ format with
+`Sphinx <http://www.sphinx-doc.org/en/master/usage/restructuredtext/index.html>`_
+extensions for documentation. Design documents shall be captured in this format.
+
+Design documents are kept under version control at the project's
+`Gerrit server <https://review.trustedfirmware.org>`_. All decisions made and
+important information gathered during the design discussion, which is not part
+of the design document shall be captured as Gerrit comments or notes for
+archiving purposes. To meet this requirement this process encourages the use of
+the Gerrit web UI for communication.
+
+
+Status of a document
+---------------------
+The status of the document is captured in a *reST filed* called *Status*.
+Bibliographic fields like the *Status* shall be kept near to the top of the
+document after the document title.
+
+Example document fragment::
+
+ TF-M Crypto Service design
+ --------------------------
+
+ :Author: Antonio de Angelis
+ :Organization: Arm Limited
+ :Contact: Antonio de Angelis <antonio.deangelis@arm.com>
+ :Status: Draft
+
+Design documents are kept in three different sections of the documentation
+reflecting the status of the document. The status of the document determines
+the section it is in. Open (*Draft* and *Detailed* status) and accepted design
+documents shall be put to the ``docs/design_documents``
+directory and rejected documents to the ``docs/design_documents/rejected``
+directory.
+
+Preparation
+-------------
+In order to work on TF-M documentation the TF-M git repository has to be
+available locally. Setting up the documentation tools will allow pre-viewing the
+documentation file in preparation.
+For information on what tools are needed please refer to
+:doc:`sw requirements </docs/user_guides/tfm_sw_requirement>`. To see how to get
+a local copy of the TF-M repository please see
+:doc:`build instructions </docs/user_guides/tfm_build_instruction>`
+
+Process steps
+-------------
+
+- Write the design proposal in the format that is described in this document
+ with the status set to *Draft*. Put it to the ``docs/design_documents``
+ directory and create a pull request.
+- Start an e-mail thread on the
+ `TF-M mailing list <mailto:tf-m@lists.trustedfirmware.org>`_ for discussing
+ the proposal.
+- Build initial consensus within the community about the proposed design
+ change, rework it according to the feedbacks and identify members who would
+ like to participate in the detailed review.
+- When the "short list" of members who are willing to participate in the
+ detailed review is established, set the *Status* field to *Detailed* and
+ push the change to Gerrit.
+- Add the members of the "short list" to the Gerrit review as reviewers.
+- The detailed discussion then takes place in the Gerrit review and gets
+ recorded there.
+ Additional changes are submitted as new commits to the review.
+- When the proposal is accepted, the status field is set to *Accepted*, the
+ change updated and merged.
+- If at any point the proposal is rejected its status field is set to
+ *Rejected*, and the document is moved to the *rejected design documents*
+ section.
+
+.. uml::
+
+ @startuml
+ !define DRAFT_DIR **docs/design_documents/**
+ !define REJECTED_DIR **docs/design_documents/rejected/**
+ !define GERRIT_URL https://review.trustedfirmware.org
+ !define GERRIT_LINK [[GERRIT_URL trustedfirmware.org]]
+ !define MAINTAINER_RST_URL https://git.trustedfirmware.org/trusted-firmware-m.git/tree/maintainers.rst
+ !define TFM_MAILING_LIST mailto:tf-m@lists.trustedfirmware.org
+ !define NO_DECISION **no**
+ !define YES_DECISION **yes**
+ !define STATUS_DRAFT **Draft**
+ !define STATUS_DETAILED **Detailed**
+ !define STATUS_REJECTED **Rejected**
+ !define STATUS_ACCEPTED **Accepted**
+
+ title Design Proposal Process
+
+ start
+ :Create first draft.in [[http://docutils.sourceforge.net/rst.html ReST format]];
+ :Set it's status to STATUS_DRAFT.;
+
+ :Add your document under DRAFT_DIR.;
+ :Create pull-request at GERRIT_LINK.;
+ partition "Initial review." {
+ :Start an e-mail thread at [[TFM_MAILING_LIST tf-m mailing list]].;
+ repeat
+ :Build initial consensus within the
+ community about the proposed design change.;
+ :Gather developers interested in detailed review.;
+ repeat while (Ready for detailed review?)
+ }
+
+ partition "Detailed review." {
+ :Set document status to STATUS_DETAILED.;
+ :Add reviewers to pull request.;
+
+ repeat
+ :Discuss design in Gerrit comments/notes.;
+ :Log the result of discussions over
+ other communication channels
+ as Gerrit comments/notes.;
+ :Push new document version if needed.;
+ repeat while (Consensus reached?)
+ }
+
+ if (Design is rejected?) then (YES_DECISION)
+ :Set document status to STATUS_REJECTED.;
+ :Move the document to REJECTED_DIR.;
+ else (NO_DECISION)
+ :Sets the document status to STATUS_ACCEPTED.;
+ endif
+
+ ://Submit// the pull-request.;
+ stop
+
+ @enduml
+
+--------------
+
+*Copyright (c) 2019, Arm Limited. All rights reserved.*