Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
emscripten-core
GitHub Repository: emscripten-core/emscripten
Path: blob/main/tools/maint/update_settings_docs.py
6165 views
1
#!/usr/bin/env python3
2
# Copyright 2021 The Emscripten Authors. All rights reserved.
3
# Emscripten is available under two separate licenses, the MIT license and the
4
# University of Illinois/NCSA Open Source License. Both these licenses can be
5
# found in the LICENSE file.
6
7
"""Convert src/settings.js into ReSt docs that get published as
8
part of the emscripten docs.
9
10
This parser for src/settings.js is somewhat fragile, and
11
comments need to be written in a ReSt friendly way. This
12
means, for example, using double backticks for keywords and
13
leaving a blank line before and after list blocks.
14
15
The parser does understand several "tags" which we use
16
settings.js. For example [compile] and [link].
17
"""
18
19
import os
20
import subprocess
21
import sys
22
23
script_dir = os.path.dirname(os.path.abspath(__file__))
24
root_dir = os.path.dirname(os.path.dirname(script_dir))
25
26
sys.path.insert(0, root_dir)
27
28
from tools.settings import (
29
COMPILE_TIME_SETTINGS,
30
DEPRECATED_SETTINGS,
31
EXPERIMENTAL_SETTINGS,
32
LEGACY_SETTINGS,
33
)
34
from tools.utils import exit_with_error, path_from_root, read_file, safe_ensure_dirs
35
36
header = '''\
37
.. _settings-reference:
38
39
============================
40
Emscripten Compiler Settings
41
============================
42
43
The following is a complete list of settings that can be passed to emscripten
44
via ``-s`` on the command line. For example ``-sASSERTIONS`` or
45
``-sASSERTIONS=0``. For more details see the :ref:`emcc <emcc-s-option-value>`
46
documentation.
47
48
Unless otherwise noted these settings only apply when linking and have no effect
49
during compilation.
50
51
.. Auto-generated by update_settings_docs.py. **DO NOT EDIT**
52
'''
53
54
all_tags = {
55
'link': '',
56
'compile+link': 'Applicable during both linking and compilation',
57
'compile': 'Only applicable during compilation',
58
'experimental': 'This is an experimental setting',
59
'deprecated': 'This setting is deprecated',
60
}
61
62
deprecated_header = '''
63
.. _deprecated-settings:
64
65
===================
66
Deprecated Settings
67
===================
68
69
The following settings have been proposed for removal from emscripten. These settings
70
still function but may be removed in a future version. If your project is using one of
71
these settings please open a bug (or reply to one of the existing bugs).
72
73
'''
74
75
legacy_header = '''
76
.. _legacy-settings:
77
78
===============
79
Legacy Settings
80
===============
81
82
The following settings no longer have any effect but are still accepted by emscripten
83
for backwards compatibility with older versions:
84
85
'''
86
87
output_file = path_from_root('site/source/docs/tools_reference/settings_reference.rst')
88
89
90
def check_tags(setting_name, tags):
91
if setting_name in COMPILE_TIME_SETTINGS and 'compile' not in tags and 'compile+link' not in tags:
92
print(tags)
93
exit_with_error(f'setting {setting_name} in COMPILE_TIME_SETTINGS but missing [compile] tag')
94
if setting_name in DEPRECATED_SETTINGS and 'deprecated' not in tags:
95
exit_with_error(f'setting {setting_name} in DEPRECATED_SETTINGS but missing [deprecated] tag')
96
if setting_name in EXPERIMENTAL_SETTINGS and 'experimental' not in tags:
97
exit_with_error(f'setting {setting_name} in EXPERIMENTAL_SETTINGS but missing [experimental] tag')
98
99
100
def write_setting(f, setting_name, setting_default, comment, tags):
101
# Convert markdown backticks to rst double backticks
102
f.write('\n.. _' + setting_name.lower() + ':\n')
103
f.write('\n' + setting_name + '\n')
104
f.write('=' * len(setting_name) + '\n\n')
105
f.write(comment + '\n')
106
for tag in tags:
107
for t in tag.split():
108
if all_tags[t]:
109
f.write('\n.. note:: ' + all_tags[t] + '\n')
110
# TODO: Properly handle multi-line values, like for INCOMING_MODULE_JS_API,
111
# which is [, newline, and then lines of content. For now print a
112
# placeholder.
113
if setting_default == '[':
114
setting_default = '(multi-line value, see settings.js)'
115
f.write('\nDefault value: ' + setting_default + '\n')
116
117
118
def write_file(f):
119
f.write(header)
120
121
current_comment = []
122
current_tags = []
123
for line in read_file(path_from_root('src/settings.js')).splitlines():
124
if not line:
125
current_comment = []
126
current_tags = []
127
if line.startswith('//'):
128
line = line[2:]
129
# Strip at most one leading space
130
if line and line[0] == ' ':
131
line = line[1:]
132
if line.startswith('[') and line.endswith(']'):
133
tag = line.strip('[')
134
tag = tag.rstrip(']')
135
if tag in all_tags:
136
current_tags.append(tag)
137
continue
138
current_comment.append(line)
139
elif line.startswith('var'):
140
# Format:
141
# var NAME = DEFAULT;
142
# Split it and strip the final ';'.
143
_, setting_name, _, setting_default = line.strip(';').split(None, 3)
144
comment = '\n'.join(current_comment).strip()
145
check_tags(setting_name, current_tags)
146
write_setting(f, setting_name, setting_default, comment, current_tags)
147
current_comment = []
148
current_tags = []
149
150
f.write(deprecated_header)
151
152
for name, desc in DEPRECATED_SETTINGS.items():
153
f.write(f' - ``{name}``: {desc}\n')
154
155
f.write(legacy_header)
156
157
for name, values, *extra_fields in LEGACY_SETTINGS:
158
desc = f'Valid values: {values}'
159
if extra_fields:
160
desc = f'{extra_fields[0]} ({desc})'
161
f.write(f' - ``{name}``: {desc}\n')
162
163
164
def main(args):
165
if '--check' in args:
166
safe_ensure_dirs(path_from_root('out'))
167
tmp_output = path_from_root('out/settings_reference.rst')
168
with open(tmp_output, 'w') as f:
169
write_file(f)
170
if read_file(tmp_output) != read_file(output_file):
171
print(f'{output_file} is out-of-date. Please run tools/maint/update_settings_docs.py')
172
subprocess.call(['diff', '-u', output_file, tmp_output])
173
return 1
174
else:
175
with open(output_file, 'w') as f:
176
write_file(f)
177
178
return 0
179
180
181
if __name__ == '__main__':
182
sys.exit(main(sys.argv[1:]))
183
184