aboutsummaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorMinos Galanakis <minos.galanakis@arm.com>2020-06-03 15:38:03 +0100
committerTamas Ban <tamas.ban@arm.com>2020-09-24 12:49:54 +0000
commitd19a19f161148b97f3ec8ccec7baebd79599f8c4 (patch)
treeb7d1f354d0a33d533b74f7bcdc3b9865b360504e /tools
parent7b95029a5864ce834e9535ce96da92be3f418a54 (diff)
downloadtrusted-firmware-m-d19a19f161148b97f3ec8ccec7baebd79599f8c4.tar.gz
Docs: Decouple from CMAKE and enable sphynx-build.
This patch is reducing the dependency of the documentation to the TrustedFirmware-M build environment. Currently CMake will copy over files from platforms, render the configuration files, sort design documents and invoke the corresponding tools to build the documentation. This patch introduces an environment communicating interface file, which CMAKE will need to populate, before calling the build command. The file copy operation has been moved over to the sphynx-build logic, and the design document’s classification is no longer required by the new user interface. The new implemenatation allows: * Documentation can be built in an identical way through the build system, retaining compatibility with existing tools, such as the CI. * It is now possible to build documentation, by just invoking sphynx-build from the build-docs directory. * Third party tools/services like readthedocs.org can now render the TF-M documentation. * Reduced CMake code size. * Documentation generating logic invokes ‘git describe’ in order to determine a version. The order of precedence is set as: Git Describe Version-> CMake hardcoded version -> Template version. * CMake logic can still toggle parts of the new logic on and off if required. * The full set of TF-M build dependencies are not longer required in order to build documentation. Just the documentation dependencies would suffice. Change-Id: I12e7bbffe9d1adb756329c46da13905e95096381 Signed-off-by: Minos Galanakis <minos.galanakis@arm.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/documentation/tfm_cmake_defaults.py220
-rw-r--r--tools/documentation/tfm_copy_files.py87
2 files changed, 307 insertions, 0 deletions
diff --git a/tools/documentation/tfm_cmake_defaults.py b/tools/documentation/tfm_cmake_defaults.py
new file mode 100644
index 000000000..e90bd6065
--- /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 000000000..09226c81c
--- /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)