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