aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build_docs/conf.py32
-rw-r--r--cmake/Common/BuildSphinxDoc.cmake78
-rw-r--r--cmake/SphinxCopyDoc.cmake65
-rw-r--r--cmake/SphinxDesignDocStatus.cmake242
-rw-r--r--docs/getting_started/tfm_build_instruction.rst41
-rw-r--r--docs/tfm_env.py.in28
-rw-r--r--doxygen/Doxyfile.in4
-rw-r--r--tools/documentation/tfm_cmake_defaults.py220
-rw-r--r--tools/documentation/tfm_copy_files.py87
9 files changed, 444 insertions, 353 deletions
diff --git a/build_docs/conf.py b/build_docs/conf.py
new file mode 100644
index 0000000000..5a83618266
--- /dev/null
+++ b/build_docs/conf.py
@@ -0,0 +1,32 @@
+# -----------------------------------------------------------------------------
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+# -----------------------------------------------------------------------------
+#
+# Configuration file override for the Sphinx documentation builder.
+#
+# This file is used when Sphinx build is invoked directly at this level.
+# It will trigger a copy-files operation and render a new configuration
+# using either auto-detected or cmake provided parameters.
+import os
+import sys
+
+# Attempt to find the tools directory by recursing up to five levels of parents
+root_path = os.path.dirname(os.path.abspath(__file__))
+
+for i in range(5):
+ root_path = os.path.dirname(root_path)
+ doc_path = os.path.join(root_path, "tools", "documentation")
+ if os.path.isdir(doc_path):
+ sys.path.insert(0, os.path.abspath(doc_path))
+sys.path.append("./")
+
+# Trigger the copy operation logic
+import tfm_copy_files
+
+# Import the rendered configuration into global scope
+from tfm_cmake_defaults import *
+
+from conf_rendered import *
diff --git a/cmake/Common/BuildSphinxDoc.cmake b/cmake/Common/BuildSphinxDoc.cmake
index ab08319c3c..e95a9277b2 100644
--- a/cmake/Common/BuildSphinxDoc.cmake
+++ b/cmake/Common/BuildSphinxDoc.cmake
@@ -72,14 +72,28 @@ if (NOT SPHINX_NODOC)
set(SPHINXCFG_OUTPUT_PATH "${CMAKE_CURRENT_BINARY_DIR}/doc_sphinx")
set(SPHINX_TMP_DOC_DIR "${CMAKE_CURRENT_BINARY_DIR}/doc_sphinx_in")
-
+ set(SPHINXCFG_CONFIGURED_FILE "${TFM_ROOT_DIR}/build_docs/conf.py")
set(SPHINXCFG_TEMPLATE_FILE "${TFM_ROOT_DIR}/docs/conf.py.in")
- set(SPHINXCFG_CONFIGURED_FILE "${SPHINXCFG_OUTPUT_PATH}/conf.py")
-
- set(SPHINX_DESIGN_DOC_ROOT "${TFM_ROOT_DIR}/docs/design_documents")
- set(SPHINX_TEMPLATE_INDEX_FILE "${SPHINX_DESIGN_DOC_ROOT}/index.rst.in")
- set(SPHINX_CONFIGURED_INDEX_FILE "${SPHINX_TMP_DOC_DIR}/docs/design_documents/index.rst")
- set(SPHINX_MAIN_INDEX_FILE "docs/index.rst")
+ set(SPHINXCFG_ENVIRONMENT_FILE "${TFM_ROOT_DIR}/docs/tfm_env.py.in")
+ set(_PDF_FILE "${SPHINXCFG_OUTPUT_PATH}/latex/TF-M.pdf")
+
+ # Set the build-tool to copy over the files to ${SPHINX_TMP_DOC_DIR~
+ set(SPHINXCFG_COPY_FILES True)
+ # Set the config to render the conf.py. If needed to build it by cmake
+ # set it to False
+ set(SPHINXCFG_RENDER_CONF True)
+
+ # TODO Reference example on how a doxygen build can be requested.
+ # Currently the logic of BuildDoxygenDoc.cmake is still used for
+ # compatibility purposes.
+ set(DOXYCFG_DOXYGEN_BUILD False)
+ if (SPHINXCFG_RENDER_CONF)
+ find_package(Doxygen 1.8.0)
+ set(DOXYCFG_DOXYGEN_CFG_DIR ${TFM_ROOT_DIR}/doxygen)
+ set(DOXYCFG_OUTPUT_PATH ${SPHINXCFG_OUTPUT_PATH}/user_manual)
+ set(DOXYCFG_ECLIPSE_DOCID "org.arm.tf-m-refman")
+ file(MAKE_DIRECTORY ${SPHINXCFG_OUTPUT_PATH}/user_manual)
+ endif()
#Version ID of TF-M.
#TODO: this shall not be hard-coded here. We need a process to define the
@@ -87,44 +101,26 @@ if (NOT SPHINX_NODOC)
set(SPHINXCFG_TFM_VERSION "v1.1")
set(SPHINXCFG_TFM_VERSION_FULL "Version 1.1")
- get_filename_component(_NDX_FILE_DIR ${SPHINX_CONFIGURED_INDEX_FILE} DIRECTORY )
-
#This command does not generates the specified output file and thus it will
#always be run. Any other command or target depending on the "run-allways"
#output will be always 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}"
- "${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}
- -D MASTER_IDX=${SPHINX_MAIN_INDEX_FILE}
- -P "${TFM_ROOT_DIR}/cmake/SphinxCopyDoc.cmake"
- WORKING_DIRECTORY "${TFM_ROOT_DIR}"
- DEPENDS run-allways
- VERBATIM
- )
+ file(REMOVE_RECURSE ${SPHINX_TMP_DOC_DIR})
+ file(MAKE_DIRECTORY ${SPHINX_TMP_DOC_DIR})
+
+ #Call configure file to fill out the message template.
+ configure_file("${SPHINXCFG_ENVIRONMENT_FILE}" "${SPHINX_TMP_DOC_DIR}/tfm_env.py" @ONLY)
+
+ file(COPY "${SPHINXCFG_CONFIGURED_FILE}" DESTINATION ${SPHINX_TMP_DOC_DIR})
add_custom_target(create_sphinx_input
SOURCES "${SPHINX_TMP_DOC_DIR}"
)
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"
+ COMMAND "${SPHINX_EXECUTABLE}" -b html "${SPHINX_TMP_DOC_DIR}" "${SPHINXCFG_OUTPUT_PATH}/html"
WORKING_DIRECTORY "${TFM_ROOT_DIR}"
DEPENDS create_sphinx_input run-allways
COMMENT "Running Sphinx to generate user guide (HTML)."
@@ -145,6 +141,15 @@ if (NOT SPHINX_NODOC)
PATTERN .buildinfo EXCLUDE
)
+ if (DOXYCFG_DOXYGEN_BUILD)
+ #Add the HTML documentation to install content
+ install(DIRECTORY ${SPHINXCFG_OUTPUT_PATH}/user_manual DESTINATION doc
+ EXCLUDE_FROM_ALL
+ COMPONENT user_guide
+ PATTERN .buildinfo EXCLUDE
+ )
+ endif()
+
#If PDF documentation is being made.
if (LATEX_PDFLATEX_FOUND)
if (NOT CMAKE_GENERATOR MATCHES "Makefiles")
@@ -156,10 +161,8 @@ if (NOT SPHINX_NODOC)
message(FATAL_ERROR "CMAKE_MAKE_PROGRAM is not set. This file must be included after the project command is run.")
endif()
- set(_PDF_FILE "${SPHINXCFG_OUTPUT_PATH}/latex/TF-M.pdf")
-
add_custom_command(OUTPUT "${SPHINXCFG_OUTPUT_PATH}/latex"
- COMMAND "${SPHINX_EXECUTABLE}" -c "${SPHINXCFG_OUTPUT_PATH}" -b latex "${SPHINX_TMP_DOC_DIR}" "${SPHINXCFG_OUTPUT_PATH}/latex"
+ COMMAND "${SPHINX_EXECUTABLE}" -b latex "${SPHINX_TMP_DOC_DIR}" "${SPHINXCFG_OUTPUT_PATH}/latex"
WORKING_DIRECTORY "${TFM_ROOT_DIR}"
DEPENDS create_sphinx_input
COMMENT "Running Sphinx to generate user guide (LaTeX)."
@@ -205,7 +208,4 @@ if (NOT SPHINX_NODOC)
-P "${CMAKE_BINARY_DIR}/cmake_install.cmake")
endif()
- #Now instantiate a Sphinx configuration file from the template.
- message(STATUS "Writing Sphinx configuration...")
- configure_file(${SPHINXCFG_TEMPLATE_FILE} ${SPHINXCFG_CONFIGURED_FILE} @ONLY)
endif()
diff --git a/cmake/SphinxCopyDoc.cmake b/cmake/SphinxCopyDoc.cmake
deleted file mode 100644
index 6bf2f073ad..0000000000
--- a/cmake/SphinxCopyDoc.cmake
+++ /dev/null
@@ -1,65 +0,0 @@
-#-------------------------------------------------------------------------------
-# Copyright (c) 2019, Arm Limited. All rights reserved.
-#
-# SPDX-License-Identifier: BSD-3-Clause
-#
-#-------------------------------------------------------------------------------
-
-#Sphinx needs all document files to be under a single directory. This script
-#copies all document files to a temporary directory while keeping the original
-#directory tree (relative location of files) except "docs/index.rst" which is
-#moved to the top level of the new tree.
-#
-# i.e.:
-# <DST_DIR>
-# | All documents from <TFM_ROOT_DIR> plus <TFM_ROOT_DIR>/docs/index.rst
-# |
-# +---docs
-# | |
-# \- all documents from <TFM_ROOT_DIR>/docs except index.rst
-# |
-# +---lib
-# | |
-# | \- All document from <TFM_ROOT_DIR>/lib keeping reativle location
-# ...
-# |
-#
-#Usage:
-# cmake -DDST_DIR=<path to destination> -DTFM_ROOT_DIR=<path to tf-m root> \
-# -DBINARY_DIR=${CMAKE_BINARY_DIR}
-# -DMASTER_IDX=<path to master index.rst> -P SphinxCopyDoc.cmake
-
-#Check input parameters
-foreach(_PARAM IN ITEMS TFM_ROOT_DIR DST_DIR BINARY_DIR MASTER_IDX)
- if (NOT DEFINED ${_PARAM})
- message(FATAL_ERROR "Variable ${_PARAM} is undefined. Please add -D${_PARAM}=<...> when calling this script.")
- endif()
-endforeach()
-
-message(STATUS "Creating document tree for Sphinx under ${DST_DIR}")
-
-#List all document files.
-file(GLOB_RECURSE _COPY_FILES
- LIST_DIRECTORIES false
- RELATIVE "${TFM_ROOT_DIR}"
- "${TFM_ROOT_DIR}/*.md"
- "${TFM_ROOT_DIR}/*.rst"
- "${TFM_ROOT_DIR}/*.png"
- "${TFM_ROOT_DIR}/*.jpg"
- "${TFM_ROOT_DIR}/dco.txt")
-
-#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)
- if (_FILE STREQUAL MASTER_IDX)
- file(COPY ${_FILE} DESTINATION "${DST_DIR}")
- else()
- file(COPY ${_FILE} DESTINATION "${DST_DIR}/${_DIR}")
- endif()
-endforeach()
diff --git a/cmake/SphinxDesignDocStatus.cmake b/cmake/SphinxDesignDocStatus.cmake
deleted file mode 100644
index ec8279c2cb..0000000000
--- a/cmake/SphinxDesignDocStatus.cmake
+++ /dev/null
@@ -1,242 +0,0 @@
-#-------------------------------------------------------------------------------
-# Copyright (c) 2019-2020, 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()
-#
-#The ":Status:" field is optional according to design proposal process.
-#Apparently, only the documents in "Accepted" status will be merged and included
-#in Sphinx build. Therefore, a design document without ":Status:" field will be
-#put in "Accepted" category by default.
-#If there are design document drafts in local environment, it is assumed that
-#developers are aware of the status of these drafts and won't be confused.
-#A message will be still thrown out when a design document doesn't contain
-#":Status:" field. It can be removed if more and more design documents don't
-#maintain that field.
-#
-#Functions are used whenever possible to avoid global variable name space
-#pollution.
-#
-
-Include(CMakeParseArguments)
-
-#Set the status value here to avoid any typo or upper/lower case trouble.
-set(ACCEPTED_STATUS "ACCEPTED")
-set(DRAFT_STATUS "DRAFT")
-set(DETAILED_STATUS "DETAILED")
-#"NO_SET" is used to mark documents without status field.
-set(NO_SET "NO_SET")
-#"INVALID_STATUS" is used to mark a document which specifies the status but the
-#status value is invalid or unrecognized.
-set(INVALID_STATUS "INVALID_STATUS")
-
-#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 without state value will be placed on the both "Accepted" list and
-#"NO_SET" 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; all files with a valid state value.
-# <prefix>_NO_SET - list; all files without status field.
-# <prefix>_INVALID_STATUS - list; all files with invalid status field.
-#
-#Examples
-# sphinx_categorize_rst(DIR ${TFM_ROOT_DIR}/docs/design_documents
-# PREFIX "DESIGN_DOCS")
-#
-function(sphinx_categorize_rst)
- #Valid state values.
- set(_STATE_VALUES ${DRAFT_STATUS} ${ACCEPTED_STATUS} ${DETAILED_STATUS}
- ${NO_SET} ${INVALID_STATUS})
-
- #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 "")
- #If a document doesn't maintain a status field, put it in
- #Accepted list by default.
- list(APPEND _STATUS_${ACCEPTED_STATUS} ${_FILE})
- #Also add the file to the "NO_SET" list. Thus it can be
- #highlighted later.
- list(APPEND _STATUS_${NO_SET} ${_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()
-
- #If the status value is invalid.
- if (_STATUS STREQUAL ${INVALID_STATUS})
- list(APPEND _STATUS_${INVALID_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_STATUS} ${ACCEPTED_STATUS} ${DETAILED_STATUS}
- ${DEFAULT_STATUS} ${INVALID_STATUS})
-
- #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")
-
- #Highlight documents without status field
- if (DEFINED _DD_${NO_SET})
- string(REPLACE ";" "\n \t" _DD_${NO_SET} "${_DD_${NO_SET}}")
- message(" The following documents are put into Accepted category without status field:\n \t${_DD_${NO_SET}}")
- endif()
-
- #Look for invalid documents
- if (DEFINED _DD_${INVALID_STATUS})
- string(REPLACE ";" "\n \t" _DD_${INVALID_STATUS} "${_DD_${INVALID_STATUS}}")
- message(WARNING " The following documents provide invalid status information:\n \t${_DD_${INVALID_STATUS}}")
- 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_STATUS} ${DETAILED_STATUS} ${ACCEPTED_STATUS})
- #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})
-
- # Strip path from the filesince index is placed in same location
- get_filename_component(_FILE ${_FILE} NAME)
- #Detailed and Draft files go to the same section
- if (_STATUS STREQUAL ${DETAILED_STATUS})
- set(_STATUS ${DRAFT_STATUS})
- endif()
-
- #Append the file to the output string
- string(APPEND ${_STATUS}_DD_LIST "\n ${_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/getting_started/tfm_build_instruction.rst b/docs/getting_started/tfm_build_instruction.rst
index 29982c0d68..a8e890b63c 100644
--- a/docs/getting_started/tfm_build_instruction.rst
+++ b/docs/getting_started/tfm_build_instruction.rst
@@ -176,9 +176,17 @@ Further details on how to integrate a new NS app with TF-M are available in the
Building the documentation
==========================
-Please ensure the dependencies for building the firmware and the
-documentation are installed as explained in the
-:doc:`software requirements <tfm_sw_requirement>`.
+Please ensure the dependencies for building the documentation are installed
+as explained in the :doc:`software requirements <tfm_sw_requirement>`. The
+requirements to build the firmware, are only required when using the CMAKE
+method
+
+There are currently two ways of building the documentation:
+- Using the CMake build system as custom targets
+- Manually using the appropriate tools (`sphinx-build`_/ `Doxygen`_)
+
+Using the CMake build-system
+----------------------------
Building PDF output is optional and can be disabled by removing LaTex from the
PATH.
@@ -188,7 +196,7 @@ PATH.
be available.
Building the Reference Manual
------------------------------
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: bash
cd <TF-M base folder>
@@ -202,7 +210,7 @@ The documentation files will be available under the directory::
cmake_doc/install/doc/reference_manual
Building the User Guide
------------------------
+^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: bash
cd <TF-M base folder>
@@ -215,6 +223,26 @@ The documentation files will be available under the directory::
cmake_doc/install/doc/user_guide
+Manually using documentation generation tools
+---------------------------------------------
+
+Invoking Sphinx-build will build both user_guide and reference_manual
+targets.
+
+.. code-block:: bash
+
+ # Build the documentation from build_docs directory
+ cd <TF-M base folder>/ build_docs/
+ sphinx-build ./ user_guide
+
+ # Build the documentation from a custom location
+ # setting the build_docs as input
+
+ # Note that using this method will still generate the reference manual
+ # to the <TF-M base folder>/build_docs/reference_manual
+ cd <TF-M base folder>/OTHER_DIR/OTHER_DIR2
+ sphinx-build <TF-M base folder>/build_docs/ DESIRED_OUTPUT_DIR
+
*********************
Configuring the build
*********************
@@ -344,6 +372,9 @@ The following table describes the differences between the configurations:
.. [7] Profile Small config doesn't cover all the platforms. Please check
Profile Small config files to find out the supported platforms.
+.. _sphinx-build: https://www.sphinx-doc.org/en/master/man/sphinx-build.html
+.. _Doxygen: https://www.doxygen.nl
+
--------------
*Copyright (c) 2017-2020, Arm Limited. All rights reserved.*
diff --git a/docs/tfm_env.py.in b/docs/tfm_env.py.in
new file mode 100644
index 0000000000..b96be484d6
--- /dev/null
+++ b/docs/tfm_env.py.in
@@ -0,0 +1,28 @@
+# -----------------------------------------------------------------------------
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+# -----------------------------------------------------------------------------
+
+# Interface file between cmake and sphynx-build. Variables will be populated
+# by cmake and evaluated by the Python builder
+
+cmake_env = { "SPHINX_TMP_DOC_DIR": "@SPHINX_TMP_DOC_DIR@",
+ "TFM_ROOT_DIR" : "@TFM_ROOT_DIR@",
+ "PLANTUML_JAR_PATH" : "@PLANTUML_JAR_PATH@",
+ "Java_JAVA_EXECUTABLE" : "@Java_JAVA_EXECUTABLE@",
+ "SPHINX_TMP_DOC_DIR" : "@SPHINX_TMP_DOC_DIR@",
+ "DOXYGEN_EXECUTABLE" : "@DOXYGEN_EXECUTABLE@",
+ "DOXYGEN_DOT_EXECUTABLE" : "@DOXYGEN_DOT_EXECUTABLE@",
+ "DOXYCFG_DOXYGEN_CFG_DIR": "@DOXYCFG_DOXYGEN_CFG_DIR@",
+ "DOXYCFG_OUTPUT_PATH": "@DOXYCFG_OUTPUT_PATH@",
+ "DOXYCFG_DOXYGEN_BUILD": "@DOXYCFG_DOXYGEN_BUILD@",
+ "DOXYCFG_ECLIPSE_DOCID": "@DOXYCFG_ECLIPSE_DOCID@",
+ "SPHINXCFG_TEMPLATE_FILE": "@SPHINXCFG_TEMPLATE_FILE@",
+ "PDF_OUTPUT_FILE": "@_PDF_FILE@",
+ "SPHINXCFG_COPY_FILES": "@SPHINXCFG_COPY_FILES@",
+ "SPHINXCFG_RENDER_CONF": "@SPHINXCFG_RENDER_CONF@",
+ "SPHINXCFG_TFM_VERSION" : "@SPHINXCFG_TFM_VERSION@",
+ "SPHINXCFG_TFM_VERSION_FULL" : "@SPHINXCFG_TFM_VERSION_FULL@"
+ }
diff --git a/doxygen/Doxyfile.in b/doxygen/Doxyfile.in
index 9a1e475041..ccfa60cc68 100644
--- a/doxygen/Doxyfile.in
+++ b/doxygen/Doxyfile.in
@@ -1,5 +1,5 @@
#-------------------------------------------------------------------------------
-# Copyright (c) 2018-2019, Arm Limited. All rights reserved.
+# Copyright (c) 2018-2020, Arm Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -58,7 +58,7 @@ PROJECT_BRIEF = Trusted Firmware-M
# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
# the logo to the output directory.
-PROJECT_LOGO = ./doxygen/TrustedFirmware-Logo_icon.png
+PROJECT_LOGO = @TFM_ROOT_DIR@/doxygen/TrustedFirmware-Logo_icon.png
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
# into which the generated documentation will be written. If a relative path is
diff --git a/tools/documentation/tfm_cmake_defaults.py b/tools/documentation/tfm_cmake_defaults.py
new file mode 100644
index 0000000000..e90bd6065e
--- /dev/null
+++ b/tools/documentation/tfm_cmake_defaults.py
@@ -0,0 +1,220 @@
+# -----------------------------------------------------------------------------
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+# -----------------------------------------------------------------------------
+
+# This module is providing the default parameters for manual Documentation
+# building. ( Without relying on CMake to determine the enviroment )
+#
+# It will however be able to communicate parameters when populated
+# by CMake (using the tfm_env.py file), and use a best-effort approach
+# to determine them when the interface file is not preset.
+
+import os
+import re
+import json
+from subprocess import check_output
+from platform import system
+
+# When called after cmake an evniroment variables file will be present
+try:
+ from tfm_env import cmake_env
+except Exception as E:
+ print("ERROR: Configuration Exception:", E)
+ cmake_env = None
+
+tfm_def_render_cmake = True
+tfm_def_copy_files = True
+tfm_def_build_doxygen = True
+
+
+def find_tfm_root(start_dir=os.path.dirname(os.path.abspath(__file__)),
+ target_files=["license.rst",
+ "dco.txt",
+ "CommonConfig.cmake"],
+ max_depth=5):
+ """ Method which attempts to find the root of the project
+ by traversing parent directoried and attempts to located each of the
+ files included in target_files list"""
+
+ tfm_root = start_dir
+
+ for i in range(max_depth):
+ tfm_root = os.path.dirname(tfm_root)
+ if set(target_files).issubset(set(os.listdir(tfm_root))):
+ return tfm_root
+ return None
+
+
+def find_package(binary_name):
+ """ Attempts to resolve the abolute path for a given application or return
+ empty string is nothing is found"""
+
+ sys_det = system()
+
+ if sys_det == "Windows":
+ cmd = "where"
+ # Window's where requires the extension
+ binary_name = binary_name + ".exe"
+ elif sys_det in ["Darwin", "Linux"]:
+ cmd = "which"
+ try:
+ return check_output([cmd, binary_name]).decode('UTF-8').strip()
+ except Exception as E:
+ return ""
+
+
+def render_cmake_file(config_map, in_file, out_file):
+ """ Read an input file containing CMAKE variables and try to
+ render them based on a configuration map. Variables not listed
+ on the map will be cleared """
+
+ # Read the input file
+ with open(in_file, "r", encoding='utf-8') as F:
+ _data = F.read()
+
+ # Render all config entires included in the map
+ for k, v in config_map.items():
+ v = v.replace("\\", "\\\\")
+ _data = re.sub(r'@%s@' % k, r'%s' % v, _data)
+
+ # Set all remaining entries to blank
+ _data = re.sub(r'@[A-Z\_]+@', "", _data)
+
+ # Create output file
+ with open(out_file, "w", encoding='utf-8') as F:
+ F.write(_data)
+
+
+# Default output director for reference_manual. It should not be empty
+tfm_def_doxy_output_dir = "reference_manual"
+
+
+if cmake_env is None:
+ # #################### Automatic Defaults ( Standalone )################# #
+
+ # Resolve ../../
+ tfm_def_root_dir = find_tfm_root()
+
+ # Set the copy files directory to whatever will be passed to sphynx-build
+ tfm_def_copy_dir = os.path.abspath(os.getcwd())
+
+ # Documentation base path
+ tfm_def_doc_root = os.path.join(tfm_def_root_dir, "docs")
+ tfm_def_copy_doc_root = os.path.join(tfm_def_copy_dir, "docs")
+
+ tfm_def_doxy_root = os.path.join(tfm_def_root_dir, "doxygen")
+
+ tfm_def_doxy_output_dir = os.path.join(tfm_def_copy_dir,
+ tfm_def_doxy_output_dir)
+
+ # Input files ( Files containing CMAKE variables )
+ tfm_def_conf_in_file = os.path.join(tfm_def_doc_root, "conf.py.in")
+ tfm_def_doxygen_in_file = os.path.join(tfm_def_doxy_root, "Doxyfile.in")
+
+ # Attempt to detect plantUML
+ _ubuntu_plantum_loc = "/usr/share/plantuml/plantuml.jar"
+ if "PLANTUML_JAR_PATH" in os.environ.keys():
+ tfm_def_plantum_loc = os.environ["PLANTUML_JAR_PATH"]
+ elif os.path.isfile(_ubuntu_plantum_loc):
+ tfm_def_plantum_loc = _ubuntu_plantum_loc
+ else:
+ tfm_def_plantum_loc = ""
+
+ # Attempt to detect the java interpreter location
+ tfm_def_java_binary = find_package("java")
+ tfm_def_doxygen_loc = find_package("doxygen")
+ tfm_def_doxygen_dot_loc = find_package("dot")
+
+else:
+ # #################### Cmake Defaults ################################## #
+ tfm_def_root_dir = os.path.abspath(cmake_env["TFM_ROOT_DIR"])
+ tfm_def_copy_dir = os.path.abspath(cmake_env["SPHINX_TMP_DOC_DIR"])
+ tfm_def_plantum_loc = os.path.abspath(cmake_env["PLANTUML_JAR_PATH"])
+ tfm_def_java_binary = os.path.abspath(cmake_env["Java_JAVA_EXECUTABLE"])
+ tfm_def_tfm_ver_shrt = cmake_env["SPHINXCFG_TFM_VERSION"]
+ tfm_def_tfm_ver_full = cmake_env["SPHINXCFG_TFM_VERSION_FULL"]
+ tfm_def_conf_in_file = cmake_env["SPHINXCFG_TEMPLATE_FILE"]
+
+ tfm_def_copy_files = True if cmake_env["SPHINXCFG_COPY_FILES"] == "True" \
+ else False
+ tfm_def_render_cmake = True \
+ if cmake_env["SPHINXCFG_RENDER_CONF"] == "True" else False
+
+ tfm_def_build_doxygen = True \
+ if cmake_env["DOXYCFG_DOXYGEN_BUILD"] == "True" else False
+
+ if tfm_def_build_doxygen:
+ tfm_def_doxy_root = cmake_env["DOXYCFG_DOXYGEN_CFG_DIR"]
+ tfm_def_doxygen_in_file = os.path.join(tfm_def_doxy_root,
+ "Doxyfile.in")
+
+ # Documentation base path
+ tfm_def_doc_root = os.path.join(tfm_def_root_dir, "docs")
+ tfm_def_copy_doc_root = os.path.join(tfm_def_copy_dir, "docs")
+
+ # Disable copyfiles for next invocation
+ cmake_env["SPHINXCFG_COPY_FILES"] = "False"
+ with open("tfm_env.py", "w", encoding='utf-8') as F:
+ F.write("cmake_env =" + json.dumps(cmake_env))
+
+
+# Version will be retrieved in that order Git -> Cmake -> Boilerplate
+try:
+ tfm_def_tfm_ver_full = check_output(["git",
+ "describe",
+ "--tags"]).decode('UTF-8').strip()
+ proj, ver, commit_no, git_hash = tfm_def_tfm_ver_full.split("-")
+
+ if (int(commit_no) > 0):
+ tfm_def_tfm_ver_shrt = tfm_def_tfm_ver_full
+ else:
+ tfm_def_tfm_ver_shrt = proj + ver
+
+except Exception as E:
+ try:
+ tfm_def_tfm_ver_shrt
+ except NameError:
+ tfm_def_tfm_ver_shrt = "v1.0.0-B"
+ try:
+ tfm_def_tfm_ver_full
+ except NameError:
+ tfm_def_tfm_ver_full = "v1.0.0-B"
+
+# #################### User Defaults ######################################## #
+
+# Directories, referenced by TF-M root, which may contain releval documents
+# which need to be broughtt over
+document_scan_dirs = ["tools", "platform"]
+
+document_scan_ext = [".rst", ".md", ".jpg", ".png"]
+
+# Other documents that should be added to the root documentation folder
+documents_extra = ["license.rst", "dco.txt"]
+
+# Output files ( After CMAKE variables have been evaluated )
+tfm_def_conf_out_file = os.path.join(tfm_def_copy_dir, "conf_rendered.py")
+if tfm_def_build_doxygen:
+ tfm_def_doxygen_out_file = os.path.join(tfm_def_doxy_root,
+ "DoxyfileCfg.in")
+
+# If env is none, the script is running as standalone. Generate it with the
+# auto-detected values set above
+if cmake_env is None:
+ cmake_env = {"TFM_ROOT_DIR": tfm_def_root_dir,
+ "DOXYGEN_EXECUTABLE": tfm_def_doxygen_loc,
+ "DOXYGEN_DOT_EXECUTABLE": tfm_def_doxygen_dot_loc,
+ "PLANTUML_JAR_PATH": tfm_def_plantum_loc,
+ "SPHINXCFG_TFM_VERSION": tfm_def_tfm_ver_shrt,
+ "SPHINXCFG_TFM_VERSION_FULL": tfm_def_tfm_ver_full,
+ "Java_JAVA_EXECUTABLE": tfm_def_java_binary,
+ "DOXYCFG_OUTPUT_PATH": tfm_def_doxy_output_dir,
+ "DOXYCFG_ECLIPSE_DOCID": "org.arm.tf-m-refman",
+ "DOXYCFG_TFM_VERSION": tfm_def_tfm_ver_full,
+ }
+# Only Override the version
+else:
+ cmake_env["SPHINXCFG_TFM_VERSION"] = tfm_def_tfm_ver_shrt
+ cmake_env["SPHINXCFG_TFM_VERSION_FULL"] = tfm_def_tfm_ver_full
diff --git a/tools/documentation/tfm_copy_files.py b/tools/documentation/tfm_copy_files.py
new file mode 100644
index 0000000000..09226c81c3
--- /dev/null
+++ b/tools/documentation/tfm_copy_files.py
@@ -0,0 +1,87 @@
+# -----------------------------------------------------------------------------
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+# -----------------------------------------------------------------------------
+
+# Interface module for pre-processing the documentation content
+# before sphynx-build is called
+#
+# It collects files from multiple sources in a intermediate location
+# before calling sphinx-build, thus overriding the limitation
+# of having the documentation share a common root directory.
+#
+# It can be triggered by simply importing the module
+import os
+from shutil import copy2, copytree, rmtree, move
+from glob import glob
+from tfm_cmake_defaults import *
+from subprocess import call
+
+
+def tfm_copy_files():
+ doc_files = []
+
+ # Recursively list all files with extensions and add them
+ for _path in document_scan_dirs:
+ _path = os.path.abspath(os.path.join(tfm_def_root_dir, _path))
+ for ext in document_scan_ext:
+ doc_files.extend([f for f in glob(os.path.join(_path,
+ "**/*%s" % ext),
+ recursive=True)])
+
+ # Add the extra files
+ for _doc_file in documents_extra:
+ _doc_file = os.path.abspath(os.path.join(tfm_def_root_dir, _doc_file))
+ if os.path.isfile(_doc_file):
+ doc_files.append(_doc_file)
+
+ # Clean up all files in target dir except conf.py and tfm_env.py
+ files = [f for f in
+ glob("*", recursive=False) if f not in ["conf.py",
+ tfm_def_conf_out_file,
+ os.path.basename(
+ tfm_def_doxy_output_dir),
+ "tfm_env.py"]]
+ for f in files:
+ if os.path.isfile(f):
+ os.remove(f)
+ elif os.path.isdir(f):
+ rmtree(f)
+
+ # Copy the documentation folder as is
+ copytree(tfm_def_doc_root, tfm_def_copy_doc_root)
+
+ # Move the index to the intermediate build directory
+ # docs/index.rst --> ./index.rst
+ move(os.path.join(tfm_def_copy_doc_root, "index.rst"), tfm_def_copy_dir)
+
+ for df in list(doc_files):
+ # Set the target filename to be cwd + relative to root path of origin
+ target_f = os.path.relpath(df, tfm_def_root_dir)
+ target_f = os.path.join(tfm_def_copy_dir, target_f)
+ # Create path for file (nested) without exception if exists
+ os.makedirs(os.path.dirname(target_f), exist_ok=True)
+ # Copy the file to new location
+ copy2(df, target_f)
+
+
+# Build Doxygen Documnetation
+if tfm_def_build_doxygen:
+ # if conf file is not provided by cmake
+ if tfm_def_render_cmake:
+ render_cmake_file(cmake_env,
+ tfm_def_doxygen_in_file,
+ tfm_def_doxygen_out_file)
+ # Call doxygen to generate the documentation
+ doxygen_bin = find_package("doxygen")
+ call([doxygen_bin, tfm_def_doxygen_out_file])
+
+# Only act if requested by defaults
+if tfm_def_copy_files:
+ tfm_copy_files()
+
+if tfm_def_render_cmake:
+ # Render the conf_py file
+ render_cmake_file(cmake_env, tfm_def_conf_in_file, tfm_def_conf_out_file)