aboutsummaryrefslogtreecommitdiff
path: root/tools/documentation/tfm_cmake_defaults.py
blob: 5fb7b86fbf7d9ee16bf47ddda4a1be25980f47c2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
# -----------------------------------------------------------------------------
# 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:
    vrex = re.compile(r'TF-Mv(?P<VER_MAJ>\d{1,2}).(?P<VER_MIN>\d{1,2}).?'
                      r'(?P<VER_HOT>\d{0,2})(?P<RC>\-RC\d)?-'
                      r'(?P<PATCH_NO>\d+)-(?P<GIT_HASH>[a-g0-9]+)')
    tfm_def_tfm_ver_full = check_output(["git",
                                         "describe",
                                         "--tags",
                                         "--long"]).decode('UTF-8').strip()

    _v = vrex.search(tfm_def_tfm_ver_full)
    proj = "TF-M"
    version  = [ _v.group("VER_MAJ"),
                 _v.group("VER_MIN"),
                 _v.group("VER_HOT"),
                 _v.group("RC")]
    commit_no  = _v.group("PATCH_NO")
    git_hash  = _v.group("GIT_HASH")

    # Sanitize the verison and remove empty entries
    version = [i.replace("-","") for i in version if i]
    tfm_def_tfm_ver_full = ".".join(version)
    tfm_def_tfm_ver_shrt = ".".join(version[:2])

    if (int(commit_no) > 0):
        tfm_def_tfm_ver_full = "%s+ ( #%s )" % (tfm_def_tfm_ver_full, git_hash)
        tfm_def_tfm_ver_shrt = "%s+ ( #%s )" % (tfm_def_tfm_ver_shrt, git_hash)

    tfm_def_tfm_ver_shrt = tfm_def_tfm_ver_full


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_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