Belle II Software  release-05-02-19
doxygen.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3 
4 # Custom builder for the module IO images.
5 
6 import os
7 import re
8 import subprocess
9 from pathlib import Path
10 from SCons.Builder import Builder
11 
12 # module in b2modmap file
13 module_re = \
14  re.compile(r'^REG_MODULE\((\S*)\)$', re.M)
15 
16 
17 def module_io_emitter(target, source, env):
18  target = []
19  if not env.get('HAS_DOT', False):
20  return (target, source)
21  for source_file in source:
22  contents = source_file.get_text_contents()
23  for entry in module_re.findall(contents):
24  target.append(os.path.join('build', 'module_io', entry + '.png'))
25  return (target, source)
26 
27 
28 def module_io(target, source, env):
29  for target_file in target:
30  # make sure the target exists even if the plot creation fails
31  Path(str(target_file)).touch()
32 
33  dir = os.path.dirname(str(target_file))
34  module = os.path.splitext(os.path.basename(str(target_file)))[0]
35  if module in ['EclDisplay', 'Rbuf2Ds', 'FastRbuf2Ds', 'Rbuf2Rbuf', 'Ds2Raw']:
36  return None
37 
38  try:
39  subprocess.run(['basf2', '--module-io', module],
40  stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, cwd=dir, timeout=60)
41  except:
42  continue
43  try:
44  subprocess.run(['dot', module + '.dot', '-Tpng', '-o', module + '.png'],
45  stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, cwd=dir, timeout=60)
46  except:
47  pass
48 
49  return None
50 
51 
52 def doxygen_groups_emitter(target, source, env):
53  return (['Doxygen.h'], [])
54 
55 
56 def doxygen_groups(target, source, env):
57  groups_file = open(str(target[0]), 'w')
58  groups_file.write("""
59 /** @defgroup DataObjects Data objects
60  */
61 
62 /** @defgroup Modules Modules
63  */
64 
65 /** @defgroup Packages Packages
66  */
67 
68 """)
69 
70  for package in env['AVAILABLE_PACKAGES']:
71  groups_file.write(f"""
72 /** @defgroup {package} {package}
73  * @ingroup Packages
74  */
75 
76 /** @defgroup {package}_dataobjects {package} data objects
77  * @ingroup {package}
78  * @ingroup Dataobjects
79  */
80 
81 /** @defgroup {package}_modules {package} modules
82  * @ingroup {package}
83  * @ingroup Modules
84  */
85 
86  """)
87  groups_file.close()
88 
89 
90 def doxyfile(target, source, env):
91  content = source[0].get_text_contents().replace('BELLE2_RELEASE', env.GetOption('doxygen'))
92  if env.get('HAS_DOT', False):
93  content = content.replace('HAVE_DOT = NO', 'HAVE_DOT = YES')
94  target_file = open(str(target[0]), 'w')
95  target_file.write(content)
96  target_file.close()
97 
98 
99 # define builder for module-io plots
100 moduleio = Builder(action=module_io, emitter=module_io_emitter)
101 moduleio.action.cmdstr = '${MODULEIOCOMSTR}'
102 
103 # define builder for doxygen
104 doxygen = Builder(action=f'doxygen $SOURCE 2>&1 > build/doxygen.log | sed "s;^{os.environ.get("BELLE2_LOCAL_DIR", "")}/;;g" 1>&2',
105  emitter=lambda target, source, env: (['build/doxygen/html/index.html'], source))
106 
107 
108 def generate(env):
109  env['BUILDERS']['ModuleIo'] = moduleio
110  env['BUILDERS']['DoxygenGroups'] = Builder(action=doxygen_groups, emitter=doxygen_groups_emitter)
111  env['BUILDERS']['Doxyfile'] = Builder(action=doxyfile)
112  env['BUILDERS']['Doxygen'] = doxygen
113  for builder in ['DoxygenGroups', 'Doxyfile', 'Doxygen']:
114  env['BUILDERS'][builder].action.cmdstr = '${DOXYGENCOMSTR}'
115 
116 
117 def exists(env):
118  return True