Package mbuild :: Module doxygen
[frames] | no frames]

Source Code for Module mbuild.doxygen

  1  #!/usr/bin/env python 
  2  # -*- python -*- 
  3  #BEGIN_LEGAL 
  4  # 
  5  #Copyright (c) 2016 Intel Corporation 
  6  # 
  7  #  Licensed under the Apache License, Version 2.0 (the "License"); 
  8  #  you may not use this file except in compliance with the License. 
  9  #  You may obtain a copy of the License at 
 10  # 
 11  #      http://www.apache.org/licenses/LICENSE-2.0 
 12  # 
 13  #  Unless required by applicable law or agreed to in writing, software 
 14  #  distributed under the License is distributed on an "AS IS" BASIS, 
 15  #  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 16  #  See the License for the specific language governing permissions and 
 17  #  limitations under the License. 
 18  #   
 19  #END_LEGAL 
 20   
 21   
 22  ############################################################################ 
 23  ## START OF IMPORTS SETUP 
 24  ############################################################################ 
 25   
 26  import sys 
 27  import os 
 28  import re 
 29  import copy 
 30  import glob 
 31  import types 
 32   
 33  try: 
 34     import mbuild 
 35  except: 
 36     s = "\nXED ERROR: mfile.py could not find mbuild."  + \ 
 37         " Should be a sibling of the xed2 directory.\n\n" 
 38     sys.stderr.write(s) 
 39     sys.exit(1) 
 40   
 41   
 42  ########################################################################### 
 43  ## DOXYGEN SUPPORT 
 44  ########################################################################### 
 45   
46 -def _doxygen_version_okay(s, want_major, want_minor, want_fix):
47 values = s.split('.') 48 49 maj =int(values[0]) 50 minor = int(values[1]) 51 fix = 0 52 if len(values) > 2: 53 # remove everything after the dash for things like: 'Doxygen 54 # 1.5.1-p1' 55 values[2] = re.sub(r'-.*$','',values[2]) 56 try: 57 fix = int(values[2]) 58 except ValueError: 59 pass 60 if (maj > 1) or \ 61 (maj == want_major and minor > want_minor) or \ 62 (maj == want_major and minor == want_minor and fix >= want_fix): 63 return True 64 return False
65
66 -def _find_doxygen(env):
67 """Find the right version of doxygen. Return a tuple of the 68 command name and a boolean indicating whether or not the version 69 checked out.""" 70 71 if env['doxygen_cmd'] == '': 72 doxygen_cmd_intel = "/usr/intel/bin/doxygen" 73 doxygen_cmd_cygwin = "C:/cygwin/bin/doxygen" 74 doxygen_cmd_mac = \ 75 "/Applications/Doxygen.app/Contents/Resources/doxygen" 76 doxygen_cmd = "doxygen" 77 78 if env['build_os'] == 'win': 79 if os.path.exists(doxygen_cmd_cygwin): 80 doxygen_cmd = doxygen_cmd_cygwin 81 else: 82 mbuild.msgb('DOXYGEN',"Could not find cygwin's doxygen," + 83 "trying doxygen from PATH") 84 elif env['build_os'] == 'lin': 85 if mbuild.verbose(1): 86 mbuild.msgb("CHECKING FOR", doxygen_cmd_intel) 87 if os.path.exists(doxygen_cmd_intel): 88 doxygen_cmd = doxygen_cmd_intel 89 elif env['build_os'] == 'mac': 90 if mbuild.verbose(1): 91 mbuild.msgb("CHECKING FOR", doxygen_cmd_mac) 92 if os.path.exists(doxygen_cmd_mac): 93 doxygen_cmd = doxygen_cmd_mac 94 else: 95 doxygen_cmd = env['doxygen_cmd'] 96 97 doxygen_cmd = env.escape_string(doxygen_cmd) 98 doxygen_okay = False 99 if mbuild.verbose(1): 100 mbuild.msgb('Checking doxygen version','...') 101 if mbuild.check_python_version(2,4): 102 try: 103 (retval, output, error_output) = \ 104 mbuild.run_command(doxygen_cmd + " --version") 105 if retval==0: 106 if len(output) > 0: 107 first_line = output[0].strip() 108 if mbuild.verbose(1): 109 mbuild.msgb("Doxygen version", first_line) 110 doxygen_okay = _doxygen_version_okay(first_line, 1,4,6) 111 else: 112 for o in output: 113 mbuild.msgb("Doxygen-version-check STDOUT", o) 114 if error_output: 115 for line in error_output: 116 mbuild.msgb("STDERR ",line.rstrip()) 117 except: 118 mbuild.die("Doxygen required by the command line options " + 119 "but no doxygen found") 120 121 return (doxygen_cmd, doxygen_okay)
122 123
124 -def _replace_match(istring, mtch, newstring, group_name):
125 """This is a lame way of avoiding regular expression backslashing 126 issues""" 127 x1= mtch.start(group_name) 128 x2= mtch.end(group_name) 129 ostring = istring[0:x1] + newstring + istring[x2:] 130 return ostring
131 132
133 -def _customize_doxygen_file(env, subs):
134 135 """Change the $(*) strings to the proper value in the config file. 136 Returns True on success""" 137 138 # doxygen wants quotes around paths with spaces 139 for k,s in subs.iteritems(): 140 if re.search(' ',s): 141 if not re.search('^".*"$',s): 142 mbuild.die("Doxygen requires quotes around strings with spaces: [%s]->[%s]" % 143 ( k,s)) 144 return False 145 146 # input and output files 147 try: 148 lines = file(env['doxygen_config']).readlines() 149 except: 150 mbuild.msgb("Could not open input file: " + env['doxygen_config']) 151 return False 152 153 env['doxygen_config_customized'] = \ 154 env.build_dir_join(os.path.basename(env['doxygen_config']) + '.customized') 155 try: 156 ofile = open(env['doxygen_config_customized'],'w') 157 except: 158 mbuild.msgb("Could not open output file: " + env['doxygen_config_customized']) 159 return False 160 161 # compile the patterns 162 rsubs = {} 163 for k,v in subs.iteritems(): 164 rsubs[k]=re.compile(r'(?P<tag>[$][(]' + k + '[)])') 165 166 olines = [] 167 for line in lines: 168 oline = line 169 for k,p in rsubs.iteritems(): 170 #print 'searching for', k, 'to replace it with', subs[k] 171 m = p.search(oline) 172 while m: 173 #print 'replacing', k, 'with', subs[k] 174 oline = _replace_match(oline, m, subs[k], 'tag') 175 m = p.search(oline) 176 olines.append(oline) 177 178 179 try: 180 for line in olines: 181 ofile.write(line) 182 except: 183 ofile.close() 184 mbuild.msgb("Could not write output file: " + env['doxygen_config_customized']) 185 return False 186 187 ofile.close() 188 return True
189
190 -def _build_doxygen_main(args, env):
191 """Customize the doxygen input file. Run the doxygen command, copy 192 in any images, and put the output in the right place.""" 193 194 if type(args) is types.ListType: 195 if len(args) < 2: 196 mbuild.die("Need subs dictionary and dummy file arg for the doxygen command " + 197 "to indicate its processing") 198 else: 199 mbuild.die("Need a list for _build_doxygen_main with the subs " + 200 "dictionary and the dummy file name") 201 202 (subs,dummy_file) = args 203 204 (doxygen_cmd, doxygen_okay) = _find_doxygen(env) 205 if not doxygen_okay: 206 msg = 'No good doxygen available on this system; ' + \ 207 'Your command line arguments\n\trequire it to be present. ' + \ 208 'Consider dropping the "doc" and "doc-build" options\n\t or ' + \ 209 'specify a path to doxygen with the --doxygen knob.\n\n\n' 210 return (1, [msg]) # failure 211 else: 212 env['DOXYGEN'] = doxygen_cmd 213 214 try: 215 okay = _customize_doxygen_file(env, subs) 216 except: 217 mbuild.die("CUSTOMIZE DOXYGEN INPUT FILE FAILED") 218 if not okay: 219 return (1, ['Doxygen customization failed']) 220 221 cmd = env['DOXYGEN'] + ' ' + \ 222 env.escape_string(env['doxygen_config_customized']) 223 if mbuild.verbose(1): 224 mbuild.msgb("RUN DOXYGEN", cmd) 225 (retval, output, error_output) = mbuild.run_command(cmd) 226 227 for line in output: 228 mbuild.msgb("DOX",line.rstrip()) 229 if error_output: 230 for line in error_output: 231 mbuild.msgb("DOX-ERROR",line.rstrip()) 232 if retval != 0: 233 mbuild.msgb("DOXYGEN FAILED") 234 mbuild.die("Doxygen run failed. Retval=", str(retval)) 235 mbuild.touch(dummy_file) 236 mbuild.msgb("DOXYGEN","succeeded") 237 return (0, []) # success
238 239 240 ########################################################################### 241 # Doxygen build 242 ###########################################################################
243 -def _empty_dir(d):
244 """return True if the directory d does not exist or if it contains no 245 files/subdirectories.""" 246 if not os.path.exists(d): 247 return True 248 for (root, subdirs, subfiles) in os.walk(d): 249 if len(subfiles) or len(subdirs): 250 return False 251 return True
252
253 -def _make_doxygen_reference_manual(env, doxygen_inputs, subs, work_queue, 254 hash_file_name='dox'):
255 """Install the doxygen reference manual the doyxgen_output_dir 256 directory. doxygen_inputs is a list of files """ 257 258 dox_dag = mbuild.dag_t(hash_file_name,env=env) 259 260 # so that the scanner can find them 261 dirs = {} 262 for f in doxygen_inputs: 263 dirs[os.path.dirname(f)]=True 264 for d in dirs.iterkeys(): 265 env.add_include_dir(d) 266 267 # make sure the config and top file are in the inptus list 268 doxygen_inputs.append(env['doxygen_config']) 269 doxygen_inputs.append(env['doxygen_top_src']) 270 271 dummy = env.build_dir_join('dummy-doxygen-' + hash_file_name) 272 273 # Run it via the builder to make it dependence driven 274 run_always = False 275 if _empty_dir(env['doxygen_install']): 276 run_always = True 277 278 if run_always: 279 _build_doxygen_main([subs,dummy], env) 280 else: 281 c1 = mbuild.plan_t(command=_build_doxygen_main, 282 args= [subs,dummy], 283 env= env, 284 input= doxygen_inputs, 285 output= dummy) 286 dox1 = dox_dag.add(env,c1) 287 288 okay = work_queue.build(dag=dox_dag) 289 phase = "DOXYGEN" 290 if not okay: 291 mbuild.die("[%s] failed. dying..." % phase) 292 if mbuild.verbose(1): 293 mbuild.msgb(phase, "build succeeded")
294 295 296 ############################################################ 297
298 -def doxygen_env(env):
299 """Add the doxygen variables to the environment""" 300 doxygen_defaults = dict( doxygen_config='', 301 doxygen_top_src='', 302 doxygen_install='', 303 doxygen_cmd='' ) 304 env.update_dict(doxygen_defaults)
305
306 -def doxygen_args(env):
307 """Add the knobs to the command line knobs parser""" 308 309 env.parser.add_option("--doxygen-install", 310 dest="doxygen_install", 311 action="store", 312 default='', 313 help="Doxygen installation directory") 314 315 env.parser.add_option("--doxygen-config", 316 dest="doxygen_config", 317 action="store", 318 default='', 319 help="Doxygen config file") 320 321 env.parser.add_option("--doxygen-top-src", 322 dest="doxygen_top_src", 323 action="store", 324 default='', 325 help="Doxygen top source file") 326 327 env.parser.add_option("--doxygen-cmd", 328 dest="doxygen_cmd", 329 action="store", 330 default='', 331 help="Doxygen command name")
332 333
334 -def doxygen_run(env, inputs, subs, work_queue, hash_file_name='dox'):
335 """Run doxygen assuming certain values are in the environment env. 336 337 @type env: env_t 338 @param env: the environment 339 340 @type inputs: list 341 @param inputs: list of input files to scan for dependences 342 343 @type subs: dictionary 344 @param subs: replacements in the config file 345 346 @type work_queue: work_queue_t 347 @param work_queue: a work queue for the build 348 349 @type hash_file_name: string 350 @param hash_file_name: used for the dummy file and mbuild hash suffix 351 """ 352 _make_doxygen_reference_manual(env, inputs, subs, work_queue, hash_file_name)
353