Skip to content

Commit 9d33843

Browse files
salkiniumchris-durand
authored andcommitted
[tools] Use ThreadPool for docs generator
1 parent a1ff223 commit 9d33843

File tree

1 file changed

+23
-12
lines changed

1 file changed

+23
-12
lines changed

tools/scripts/docs_modm_io_generator.py

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,13 @@
1919
import argparse
2020
import datetime
2121
import platform
22-
import multiprocessing as mp
22+
import subprocess
23+
from multiprocessing.pool import ThreadPool
2324
from pathlib import Path
2425
from jinja2 import Environment, FileSystemLoader
2526
from collections import defaultdict
2627

28+
is_running_on_macos = "macOS" in platform.platform()
2729
def repopath(path):
2830
return Path(__file__).absolute().parents[2] / path
2931
def relpath(path):
@@ -101,26 +103,32 @@ def main():
101103
test_group.add_argument("--test2", "-t2", action='store_true', help="Test mode: generate only a few targets. List has targets from the real target list.")
102104
parser.add_argument("--jobs", "-j", type=int, default=2, help="Number of parallel doxygen processes")
103105
parser.add_argument("--local-temp", "-l", action='store_true', help="Create temporary directory inside current working directory")
104-
group = parser.add_mutually_exclusive_group(required=True)
106+
group = parser.add_mutually_exclusive_group()
105107
group.add_argument("--compress", "-c", action='store_true', help="Compress output into gzip archive")
106108
group.add_argument("--output", "-o", type=str, help="Output directory")
107109
parser.add_argument("--overwrite", "-f", action='store_true', help="Overwrite existing data in output directory (Removes all files from output directory.)")
108110
parser.add_argument("--deduplicate", "-d", action='store_true', help="Deduplicate identical files with symlinks.")
111+
parser.add_argument("--target-job", help="Create a single target from job string.")
109112
args = parser.parse_args()
110113

114+
# Called by the thread pool below as a workaround for buggy multiprocessing
115+
if args.target_job:
116+
exit(0 if create_target(args.target_job) else -1)
117+
111118
device_list, board_list, family_list = get_targets()
112119
if args.test:
113120
device_list = ["stm32f103c8t6", "stm32f417zgt6"] + family_list
114-
device_list = list(set(device_list))
115121
board_list = [("arduino-nano", "atmega328p-au"), ("arduino-uno", "atmega328p-au"), ("nucleo-g474re", "stm32g474ret6"),
116122
("blue-pill", "stm32f103c8t6"), ("feather-m0", "samd21g18a-uu"), ("disco-f469ni", "stm32f469nih6")]
117123
elif args.test2:
118124
device_list = ["hosted-linux", "atmega328p-pu", "stm32f103zgt7"]
119125
board_list = [("nucleo-g474re", "stm32g474ret6")]
126+
device_list = list(set(device_list))
120127

121128
final_output_dir = Path(args.output).absolute() if args.output else "."
122129
template_path = os.path.realpath(os.path.dirname(sys.argv[0]))
123130
cwd = Path().cwd()
131+
filepath = os.path.abspath(__file__)
124132
if args.local_temp:
125133
temp_dir = str(cwd)
126134
else:
@@ -136,16 +144,16 @@ def main():
136144
print("Starting to generate documentation...")
137145
template_overview(output_dir, device_list, board_list, template_path)
138146
print("... for {} devices, estimated memory footprint is {} MB".format(len(device_list) + len(board_list), (len(device_list)*70)+2000))
139-
with mp.get_context("spawn").Pool(args.jobs) as pool:
147+
with ThreadPool(args.jobs) as pool:
140148
# We can only pass one argument to pool.map
141-
devices = ["{}|{}|{}||{}".format(modm_path, tempdir, dev, args.deduplicate) for dev in device_list]
142-
devices += ["{}|{}|{}|{}|{}".format(modm_path, tempdir, dev, brd, args.deduplicate) for (brd, dev) in board_list]
143-
results = pool.map(create_target, devices)
149+
devices = [f"python3 {filepath} --target-job '{modm_path}|{tempdir}|{dev}||{args.deduplicate}'" for dev in device_list]
150+
devices += [f"python3 {filepath} --target-job '{modm_path}|{tempdir}|{dev}|{brd}|{args.deduplicate}'" for (brd, dev) in board_list]
151+
results = pool.map(lambda d: subprocess.run(d, shell=True).returncode, list(set(devices)))
144152
# output_dir.rename(cwd / 'modm-api-docs')
145153
if args.compress:
146154
print("Zipping docs ...")
147155
# Zipping may take more than 10 minutes
148-
os.system("(cd {} && tar -czvf {} .)".format(str(output_dir), str(cwd / 'modm-api-docs.tar.gz')))
156+
os.system(f"(cd {str(output_dir)} && {'g' if is_running_on_macos else ''}tar --checkpoint=.100 -czf {str(cwd / 'modm-api-docs.tar.gz')} .)")
149157
# shutil.make_archive(str(cwd / 'modm-api-docs'), 'gztar', str(output_dir))
150158
else:
151159
if args.overwrite and final_output_dir.exists():
@@ -157,8 +165,9 @@ def main():
157165
os.remove(i)
158166
print('Moving {} -> {}'.format(output_dir, final_output_dir))
159167
#shutil.move(str(output_dir) + '/', str(final_output_dir))
168+
print(f"Moving {output_dir} -> {final_output_dir}")
160169
output_dir.rename(final_output_dir)
161-
return results.count(False)
170+
return results.count(0) == len(results)
162171

163172

164173
def create_target(argument):
@@ -209,6 +218,7 @@ def create_target(argument):
209218
key = file.relative_to(tempdir).parts[4:]
210219
if key:
211220
symlinks[os.path.join(*key)].append(file)
221+
dot_counter = 0
212222
for file in srcdir.rglob('*'):
213223
if file.is_dir():
214224
print(end="", flush=True)
@@ -220,7 +230,8 @@ def create_target(argument):
220230
del symlinks[key]
221231
fhash = hash(file.read_bytes())
222232
if fhash in symlinks:
223-
print(".", end="")
233+
dot_counter += 1
234+
if dot_counter % 30 == 0: print(".", end="")
224235
rpath = symlinks[fhash][0].relative_to(tempdir / 'output/develop/api')
225236
lpath = os.path.relpath(srcdir, file.parent)
226237
sympath = os.path.join("..", lpath, rpath)
@@ -229,8 +240,8 @@ def create_target(argument):
229240
file.symlink_to(sympath)
230241

231242
# Only move folder *after* deduplication to prevent race condition with file.unlink()
243+
print(f"\nMoving {srcdir.relative_to(tempdir)} -> {destdir.relative_to(tempdir)}", flush=True)
232244
srcdir.rename(destdir)
233-
print(end="", flush=True)
234245
return True
235246
except Exception as e:
236247
print("Error generating documentation for device {}: {}".format(output_dir, e))
@@ -258,4 +269,4 @@ def template_overview(output_dir, device_list, board_list, template_path):
258269

259270

260271
if __name__ == "__main__":
261-
exit(main())
272+
exit(0 if main() else -1)

0 commit comments

Comments
 (0)