xref: /petsc/doc/build_c2html.py (revision ec83d4343a5cd247d99e59cd3c6992d2bb8a3b9b)
1*ec83d434SBarry Smith#!/usr/bin/env python
2*ec83d434SBarry Smith""" Builds the html files for all the source"""
3*ec83d434SBarry Smith
4*ec83d434SBarry Smithimport os
5*ec83d434SBarry Smithimport re
6*ec83d434SBarry Smithimport subprocess
7*ec83d434SBarry Smithimport pathlib
8*ec83d434SBarry Smithfrom itertools import chain
9*ec83d434SBarry Smith
10*ec83d434SBarry Smithdef compute_make_np(i):
11*ec83d434SBarry Smith  '''Number of cores to run make c2html on'''
12*ec83d434SBarry Smith  f16 = .80
13*ec83d434SBarry Smith  f32 = .65
14*ec83d434SBarry Smith  f64 = .50
15*ec83d434SBarry Smith  f99 = .30
16*ec83d434SBarry Smith  if (i<=2):    return 2
17*ec83d434SBarry Smith  elif (i<=4):  return i
18*ec83d434SBarry Smith  elif (i<=16): return int(4+(i-4)*f16)
19*ec83d434SBarry Smith  elif (i<=32): return int(4+12*f16+(i-16)*f32)
20*ec83d434SBarry Smith  elif (i<=64): return int(4+12*f16+16*f32+(i-32)*f64)
21*ec83d434SBarry Smith  else:         return int(4+12*f16+16*f32+32*f64+(i-64)*f99)
22*ec83d434SBarry Smith
23*ec83d434SBarry Smithdef main(petsc_dir,loc,c2html,mapnames):
24*ec83d434SBarry Smith  os.chdir(petsc_dir)
25*ec83d434SBarry Smith
26*ec83d434SBarry Smith  # reformat file that maps manual pages to directory location and add MPI manual pages
27*ec83d434SBarry Smith  with open('htmlmap.tmp', "w") as fdw, open(os.path.join(petsc_dir,'doc','manualpages','htmlmap'), "r") as fd:
28*ec83d434SBarry Smith    fdw.write(fd.read().replace('man+manualpages/','man+HTML_ROOT/manualpages/'))
29*ec83d434SBarry Smith  with open('htmlmap.tmp', "a") as fdw, open(os.path.join(petsc_dir,'doc','manualpages','mpi.www.index'), "r") as fd:
30*ec83d434SBarry Smith    fdw.write(fd.read())
31*ec83d434SBarry Smith
32*ec83d434SBarry Smith  # walk directories generating list of all source code that needs processing and creating index.html for each directory
33*ec83d434SBarry Smith  SKIPDIRS = set('public html benchmarks output arch doc binding config petsc-doc lib bin .git systems share mpiuni kernels khash valgrind interfaces data linter'.split())
34*ec83d434SBarry Smith  SUFFIXES = set('.F90 .F .c .cxx .cpp .h .cu'.split())
35*ec83d434SBarry Smith  allfiles = []
36*ec83d434SBarry Smith  for root, dirs, files in chain.from_iterable(os.walk(path) for path in [petsc_dir]):
37*ec83d434SBarry Smith    dirs[:] = [d for d in dirs if not any([s for s in SKIPDIRS if d.startswith(s)])]
38*ec83d434SBarry Smith    root = root[len(petsc_dir)+1:]
39*ec83d434SBarry Smith    if not root: continue
40*ec83d434SBarry Smith    if not os.path.isdir(os.path.join(loc,root)): os.makedirs(os.path.join(loc,root))
41*ec83d434SBarry Smith    allfiles.extend([os.path.join(loc,root,f+'.html') for f in files if any([s for s in SUFFIXES if f.endswith(s)])])
42*ec83d434SBarry Smith
43*ec83d434SBarry Smith    # create index.html file for each directory
44*ec83d434SBarry Smith    with open(os.path.join(loc,root,'index.html'),'w') as fdw:
45*ec83d434SBarry Smith      if root.startswith('src'):
46*ec83d434SBarry Smith
47*ec83d434SBarry Smith        # get MANSEC from the makefile and copy the MANSEC basic information into the index
48*ec83d434SBarry Smith        # TODO: the text is actually .md so needs processing
49*ec83d434SBarry Smith        if os.path.isfile(os.path.join(root,'makefile')):
50*ec83d434SBarry Smith          with open(os.path.join(root,'makefile')) as mklines:
51*ec83d434SBarry Smith            mansecl = [line for line in mklines if line.startswith('MANSEC')]
52*ec83d434SBarry Smith            if mansecl:
53*ec83d434SBarry Smith              mansec = re.sub('MANSEC[ ]*=[ ]*','',mansecl[0]).strip('\n').strip()
54*ec83d434SBarry Smith              with open(os.path.join('doc','manualpages','MANSECHeaders',mansec)) as fd:
55*ec83d434SBarry Smith                fdw.write(fd.read())
56*ec83d434SBarry Smith
57*ec83d434SBarry Smith      fdw.write('\n<p>\n')
58*ec83d434SBarry Smith
59*ec83d434SBarry Smith      # TODO: use HTML lists for the list below
60*ec83d434SBarry Smith
61*ec83d434SBarry Smith      # list examples
62*ec83d434SBarry Smith      if root.find('/tests') > -1 or root.find('tutorials') > -1:
63*ec83d434SBarry Smith        fdw.write('\n<p>\nExamples\n<p>')
64*ec83d434SBarry Smith        for f in files:
65*ec83d434SBarry Smith          if any([s for s in SUFFIXES if f.endswith(s)]):
66*ec83d434SBarry Smith            with open(os.path.join(root,f)) as fd:
67*ec83d434SBarry Smith              line = fd.readline()
68*ec83d434SBarry Smith              l = line.find('char help[] = ')
69*ec83d434SBarry Smith              if l > -1:
70*ec83d434SBarry Smith                s = line.find('\\n')
71*ec83d434SBarry Smith                line = line[l + 15:s]
72*ec83d434SBarry Smith              else: line = ''
73*ec83d434SBarry Smith              fdw.write('<a href="' + f + '.html">' + f + ': ' + line + '</a><br>\n')
74*ec83d434SBarry Smith
75*ec83d434SBarry Smith      # list source code
76*ec83d434SBarry Smith      else:
77*ec83d434SBarry Smith        if any([f for f in files if any([s for s in SUFFIXES if f.endswith(s)])]):
78*ec83d434SBarry Smith          fdw.write('\n<p>\nSource files\n<p>')
79*ec83d434SBarry Smith        for f in files:
80*ec83d434SBarry Smith          if any([s for s in SUFFIXES if f.endswith(s)]):
81*ec83d434SBarry Smith            fdw.write('<a href=\"' + f + '.html\">' + f + '</a><br>\n')
82*ec83d434SBarry Smith
83*ec83d434SBarry Smith      # list subdirectories
84*ec83d434SBarry Smith      if dirs:
85*ec83d434SBarry Smith        fdw.write('\n<p>\nDirectories\n<p>')
86*ec83d434SBarry Smith      for d in dirs:
87*ec83d434SBarry Smith        fdw.write('<a href="' + os.path.join(d,'index.html') + '">' + d + '</a><br>\n')
88*ec83d434SBarry Smith
89*ec83d434SBarry Smith  # create makefile that will run c2html on all source files in parallel
90*ec83d434SBarry Smith  git_sha = subprocess.check_output(['git', 'rev-parse', 'HEAD'], text=True).rstrip()
91*ec83d434SBarry Smith  with open(os.path.join(petsc_dir,'c2html.mk'),'w') as fd:
92*ec83d434SBarry Smith    fd.write('files = ')
93*ec83d434SBarry Smith    fd.write(' '.join(allfiles))
94*ec83d434SBarry Smith    fd.write('\n')
95*ec83d434SBarry Smith    fd.write('\n')
96*ec83d434SBarry Smith    fd.write(os.path.join(loc,'%.html')+' : %\n')
97*ec83d434SBarry Smith    fd.write('	@' + os.path.join(petsc_dir,'doc','build_c2html_file.py') + ' ' + petsc_dir + ' ' + loc + ' '+ git_sha + ' ' + c2html + ' ' + mapnames + ' $< $@\n')
98*ec83d434SBarry Smith    fd.write('\n')
99*ec83d434SBarry Smith    fd.write('all: $(files)\n')
100*ec83d434SBarry Smith
101*ec83d434SBarry Smith  import multiprocessing
102*ec83d434SBarry Smith  command = ['make', '-j', str(compute_make_np(multiprocessing.cpu_count())), '-f', 'c2html.mk', 'all']
103*ec83d434SBarry Smith  subprocess.run(command, cwd=petsc_dir, check=True)
104*ec83d434SBarry Smith
105*ec83d434SBarry Smith  os.unlink('c2html.mk')
106*ec83d434SBarry Smith  os.unlink('htmlmap.tmp')
107*ec83d434SBarry Smith
108*ec83d434SBarry Smithif __name__ == "__main__":
109*ec83d434SBarry Smith  main(sys.argv[1],sys.argv[2],sys.argv[3],sys.argv[4])
110