[SyncFS] Build indexes from FileTracker entries on disk.
[chromium-blink-merge.git] / native_client_sdk / src / doc / doxygen / generate_docs.py
blob79a013c1ec643c43b12eb2dfec6b44a60f9c3687
1 #!/usr/bin/python
3 # Copyright (c) 2014 The Chromium Authors. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file.
7 import collections
8 import json
9 import optparse
10 import os
11 import shutil
12 import subprocess
13 import sys
14 import tempfile
15 import urllib2
18 SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
19 DOC_DIR = os.path.dirname(SCRIPT_DIR)
22 ChannelInfo = collections.namedtuple('ChannelInfo', ['branch', 'version'])
25 def Trace(msg):
26 if Trace.verbose:
27 sys.stderr.write(str(msg) + '\n')
29 Trace.verbose = False
32 def GetChannelInfo():
33 url = 'http://omahaproxy.appspot.com/json'
34 u = urllib2.urlopen(url)
35 try:
36 data = json.loads(u.read())
37 finally:
38 u.close()
40 channel_info = {}
41 for os_row in data:
42 osname = os_row['os']
43 if osname not in ('win', 'mac', 'linux'):
44 continue
45 for version_row in os_row['versions']:
46 channel = version_row['channel']
47 # We don't display canary docs.
48 if channel == 'canary':
49 continue
51 version = version_row['version'].split('.')[0] # Major version
52 branch = version_row['true_branch']
53 if branch is None:
54 branch = 'trunk'
56 if channel in channel_info:
57 existing_info = channel_info[channel]
58 if branch != existing_info.branch:
59 sys.stderr.write('Warning: found different branch numbers for '
60 'channel %s: %s vs %s. Using %s.\n' % (
61 channel, branch, existing_info.branch, existing_info.branch))
62 else:
63 channel_info[channel] = ChannelInfo(branch, version)
65 return channel_info
68 def RemoveFile(filename):
69 if os.path.exists(filename):
70 os.remove(filename)
73 def RemoveDir(dirname):
74 if os.path.exists(dirname):
75 shutil.rmtree(dirname)
78 def GetSVNRepositoryRoot(branch):
79 if branch == 'trunk':
80 return 'http://src.chromium.org/chrome/trunk/src'
81 return 'http://src.chromium.org/chrome/branches/%s/src' % branch
84 def CheckoutPepperDocs(branch, doc_dirname):
85 Trace('Removing directory %s' % doc_dirname)
86 RemoveDir(doc_dirname)
88 svn_root_url = GetSVNRepositoryRoot(branch)
90 for subdir in ('api', 'generators', 'cpp', 'utility'):
91 url = svn_root_url + '/ppapi/%s' % subdir
92 cmd = ['svn', 'co', url, os.path.join(doc_dirname, subdir)]
93 Trace('Checking out docs into %s:\n %s' % (doc_dirname, ' '.join(cmd)))
94 subprocess.check_call(cmd)
96 # The IDL generator needs PLY (a python lexing library); check it out into
97 # generators.
98 url = svn_root_url + '/third_party/ply'
99 ply_dirname = os.path.join(doc_dirname, 'generators', 'ply')
100 cmd = ['svn', 'co', url, ply_dirname]
101 Trace('Checking out PLY into %s:\n %s' % (ply_dirname, ' '.join(cmd)))
102 subprocess.check_call(cmd)
105 def FixPepperDocLinks(doc_dirname):
106 # TODO(binji): We can remove this step when the correct links are in the
107 # stable branch.
108 Trace('Looking for links to fix in Pepper headers...')
109 for root, dirs, filenames in os.walk(doc_dirname):
110 # Don't recurse into .svn
111 if '.svn' in dirs:
112 dirs.remove('.svn')
114 for filename in filenames:
115 header_filename = os.path.join(root, filename)
116 Trace(' Checking file %r...' % header_filename)
117 replacements = {
118 '<a href="/native-client/{{pepperversion}}/devguide/coding/audio">':
119 '<a href="/native-client/devguide/coding/audio.html">',
120 '<a href="/native-client/devguide/coding/audio">':
121 '<a href="/native-client/devguide/coding/audio.html">',
122 '<a href="/native-client/{{pepperversion}}/pepperc/globals_defs"':
123 '<a href="globals_defs.html"',
124 '<a href="../pepperc/ppb__image__data_8h.html">':
125 '<a href="../c/ppb__image__data_8h.html">'}
127 with open(header_filename) as f:
128 lines = []
129 replaced = False
130 for line in f:
131 for find, replace in replacements.iteritems():
132 pos = line.find(find)
133 if pos != -1:
134 Trace(' Found %r...' % find)
135 replaced = True
136 line = line[:pos] + replace + line[pos + len(find):]
137 lines.append(line)
139 if replaced:
140 Trace(' Writing new file.')
141 with open(header_filename, 'w') as f:
142 f.writelines(lines)
145 def GenerateCHeaders(pepper_version, doc_dirname):
146 script = os.path.join(os.pardir, 'generators', 'generator.py')
147 cwd = os.path.join(doc_dirname, 'api')
148 out_dirname = os.path.join(os.pardir, 'c')
149 cmd = [sys.executable, script, '--cgen', '--release', 'M' + pepper_version,
150 '--wnone', '--dstroot', out_dirname]
151 Trace('Generating C Headers for version %s\n %s' % (
152 pepper_version, ' '.join(cmd)))
153 subprocess.check_call(cmd, cwd=cwd)
156 def GenerateDoxyfile(template_filename, out_dirname, doc_dirname, doxyfile):
157 Trace('Writing Doxyfile "%s" (from template %s)' % (
158 doxyfile, template_filename))
160 with open(template_filename) as f:
161 data = f.read()
163 with open(doxyfile, 'w') as f:
164 f.write(data % {
165 'out_dirname': out_dirname,
166 'doc_dirname': doc_dirname,
167 'script_dirname': SCRIPT_DIR})
170 def RunDoxygen(out_dirname, doxyfile):
171 Trace('Removing old output directory %s' % out_dirname)
172 RemoveDir(out_dirname)
174 Trace('Making new output directory %s' % out_dirname)
175 os.makedirs(out_dirname)
177 cmd = ['doxygen', doxyfile]
178 Trace('Running Doxygen:\n %s' % ' '.join(cmd))
179 subprocess.check_call(cmd)
182 def RunDoxyCleanup(out_dirname):
183 script = os.path.join(SCRIPT_DIR, 'doxy_cleanup.py')
184 cmd = [sys.executable, script, out_dirname]
185 if Trace.verbose:
186 cmd.append('-v')
187 Trace('Running doxy_cleanup:\n %s' % ' '.join(cmd))
188 subprocess.check_call(cmd)
191 def RunRstIndex(kind, channel, pepper_version, out_dirname, out_rst_filename):
192 assert kind in ('root', 'c', 'cpp')
193 script = os.path.join(SCRIPT_DIR, 'rst_index.py')
194 cmd = [sys.executable, script,
195 '--' + kind,
196 '--channel', channel,
197 '--version', pepper_version,
198 out_dirname,
199 '-o', out_rst_filename]
200 Trace('Running rst_index:\n %s' % ' '.join(cmd))
201 subprocess.check_call(cmd)
204 def GenerateDocs(root_dirname, channel, pepper_version, branch):
205 Trace('Generating docs for %s (branch %s)' % (channel, branch))
206 pepper_dirname = 'pepper_%s' % channel
207 out_dirname = os.path.join(root_dirname, pepper_dirname)
209 try:
210 svn_dirname = tempfile.mkdtemp(prefix=pepper_dirname)
211 doxyfile_dirname = tempfile.mkdtemp(prefix='%s_doxyfiles' % pepper_dirname)
213 CheckoutPepperDocs(branch, svn_dirname)
214 FixPepperDocLinks(svn_dirname)
215 GenerateCHeaders(pepper_version, svn_dirname)
217 doxyfile_c = ''
218 doxyfile_cpp = ''
220 # Generate Root index
221 rst_index_root = os.path.join(DOC_DIR, pepper_dirname, 'index.rst')
222 RunRstIndex('root', channel, pepper_version, out_dirname, rst_index_root)
224 # Generate C docs
225 out_dirname_c = os.path.join(out_dirname, 'c')
226 doxyfile_c = os.path.join(doxyfile_dirname, 'Doxyfile.c.%s' % channel)
227 doxyfile_c_template = os.path.join(SCRIPT_DIR, 'Doxyfile.c.template')
228 rst_index_c = os.path.join(DOC_DIR, pepper_dirname, 'c', 'index.rst')
229 GenerateDoxyfile(doxyfile_c_template, out_dirname_c, svn_dirname,
230 doxyfile_c)
231 RunDoxygen(out_dirname_c, doxyfile_c)
232 RunDoxyCleanup(out_dirname_c)
233 RunRstIndex('c', channel, pepper_version, out_dirname_c, rst_index_c)
235 # Generate C++ docs
236 out_dirname_cpp = os.path.join(out_dirname, 'cpp')
237 doxyfile_cpp = os.path.join(doxyfile_dirname, 'Doxyfile.cpp.%s' % channel)
238 doxyfile_cpp_template = os.path.join(SCRIPT_DIR, 'Doxyfile.cpp.template')
239 rst_index_cpp = os.path.join(DOC_DIR, pepper_dirname, 'cpp', 'index.rst')
240 GenerateDoxyfile(doxyfile_cpp_template, out_dirname_cpp, svn_dirname,
241 doxyfile_cpp)
242 RunDoxygen(out_dirname_cpp, doxyfile_cpp)
243 RunDoxyCleanup(out_dirname_cpp)
244 RunRstIndex('cpp', channel, pepper_version, out_dirname_cpp, rst_index_cpp)
245 finally:
246 # Cleanup
247 RemoveDir(svn_dirname)
248 RemoveDir(doxyfile_dirname)
251 def main(argv):
252 parser = optparse.OptionParser(usage='Usage: %prog [options] <out_directory>')
253 parser.add_option('-v', '--verbose',
254 help='Verbose output', action='store_true')
255 options, dirs = parser.parse_args(argv)
257 if options.verbose:
258 Trace.verbose = True
260 if len(dirs) != 1:
261 parser.error('Expected an output directory')
263 channel_info = GetChannelInfo()
264 for channel, info in channel_info.iteritems():
265 GenerateDocs(dirs[0], channel, info.version, info.branch)
267 return 0
270 if __name__ == '__main__':
271 try:
272 rtn = main(sys.argv[1:])
273 except KeyboardInterrupt:
274 sys.stderr.write('%s: interrupted\n' % os.path.basename(__file__))
275 rtn = 1
276 sys.exit(rtn)