Send a crash report when a hung process is detected.
[chromium-blink-merge.git] / native_client_sdk / src / build_tools / generate_make.py
blob61aaaebf64436ca140ab67bd74d1b98b0d38f57e
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
5 import json
6 import os
7 import sys
9 import buildbot_common
10 import build_version
11 import getos
12 from buildbot_common import ErrorExit
13 from easy_template import RunTemplateFileIfChanged
14 from build_paths import SDK_RESOURCE_DIR
16 def Trace(msg):
17 if Trace.verbose:
18 sys.stderr.write(str(msg) + '\n')
19 Trace.verbose = False
22 def IsExample(desc):
23 dest = desc['DEST']
24 return dest.startswith(('examples', 'tests', 'getting_started'))
27 def GenerateSourceCopyList(desc):
28 sources = []
29 # Some examples use their own Makefile/sources/etc.
30 if 'TARGETS' not in desc:
31 # Only copy the DATA files.
32 return desc.get('DATA', [])
34 # Add sources for each target
35 for target in desc['TARGETS']:
36 sources.extend(target['SOURCES'])
38 # And HTML and data files
39 sources.extend(desc.get('DATA', []))
41 if IsExample(desc):
42 sources.append('common.js')
43 if not desc.get('NO_PACKAGE_FILES'):
44 sources.extend(['icon128.png', 'background.js'])
46 return sources
49 def GetSourcesDict(sources):
50 source_map = {}
51 for key in ['.c', '.cc']:
52 source_list = [fname for fname in sources if fname.endswith(key)]
53 if source_list:
54 source_map[key] = source_list
55 else:
56 source_map[key] = []
57 return source_map
60 def GetProjectObjects(source_dict):
61 object_list = []
62 for key in ['.c', '.cc']:
63 for src in source_dict[key]:
64 object_list.append(os.path.splitext(src)[0])
65 return object_list
68 def GetPlatforms(plat_list, plat_filter, first_toolchain):
69 platforms = []
70 for plat in plat_list:
71 if plat in plat_filter:
72 platforms.append(plat)
74 if first_toolchain:
75 return [platforms[0]]
76 return platforms
79 def ErrorMsgFunc(text):
80 sys.stderr.write(text + '\n')
83 def AddMakeBat(pepperdir, makepath):
84 """Create a simple batch file to execute Make.
86 Creates a simple batch file named make.bat for the Windows platform at the
87 given path, pointing to the Make executable in the SDK."""
89 makepath = os.path.abspath(makepath)
90 if not makepath.startswith(pepperdir):
91 ErrorExit('Make.bat not relative to Pepper directory: ' + makepath)
93 makeexe = os.path.abspath(os.path.join(pepperdir, 'tools'))
94 relpath = os.path.relpath(makeexe, makepath)
96 fp = open(os.path.join(makepath, 'make.bat'), 'wb')
97 outpath = os.path.join(relpath, 'make.exe')
99 # Since make.bat is only used by Windows, for Windows path style
100 outpath = outpath.replace(os.path.sep, '\\')
101 fp.write('@%s %%*\n' % outpath)
102 fp.close()
105 def FindFile(name, srcroot, srcdirs):
106 checks = []
107 for srcdir in srcdirs:
108 srcfile = os.path.join(srcroot, srcdir, name)
109 srcfile = os.path.abspath(srcfile)
110 if os.path.exists(srcfile):
111 return srcfile
112 else:
113 checks.append(srcfile)
115 ErrorMsgFunc('%s not found in:\n\t%s' % (name, '\n\t'.join(checks)))
116 return None
119 def IsNexe(desc):
120 for target in desc['TARGETS']:
121 if target['TYPE'] == 'main':
122 return True
123 return False
126 def ProcessHTML(srcroot, dstroot, desc, toolchains, configs, first_toolchain):
127 name = desc['NAME']
128 nmf = desc['TARGETS'][0]['NAME']
129 outdir = os.path.join(dstroot, desc['DEST'], name)
130 srcpath = os.path.join(srcroot, 'index.html')
131 dstpath = os.path.join(outdir, 'index.html')
133 tools = GetPlatforms(toolchains, desc['TOOLS'], first_toolchain)
135 path = "{tc}/{config}"
136 replace = {
137 'title': desc['TITLE'],
138 'attrs':
139 'data-name="%s" data-tools="%s" data-configs="%s" data-path="%s"' % (
140 nmf, ' '.join(tools), ' '.join(configs), path),
142 RunTemplateFileIfChanged(srcpath, dstpath, replace)
145 def GenerateManifest(srcroot, dstroot, desc):
146 outdir = os.path.join(dstroot, desc['DEST'], desc['NAME'])
147 srcpath = os.path.join(SDK_RESOURCE_DIR, 'manifest.json.template')
148 dstpath = os.path.join(outdir, 'manifest.json')
149 permissions = desc.get('PERMISSIONS', [])
150 combined_permissions = list(permissions)
151 socket_permissions = desc.get('SOCKET_PERMISSIONS', [])
152 if socket_permissions:
153 combined_permissions.append({'socket': socket_permissions})
154 filesystem_permissions = desc.get('FILESYSTEM_PERMISSIONS', [])
155 if filesystem_permissions:
156 combined_permissions.append({'fileSystem': filesystem_permissions})
157 pretty_permissions = json.dumps(combined_permissions,
158 sort_keys=True, indent=4)
159 replace = {
160 'name': desc['TITLE'],
161 'description': '%s Example' % desc['TITLE'],
162 'key': True,
163 'channel': None,
164 'permissions': pretty_permissions,
165 'multi_platform': desc.get('MULTI_PLATFORM', False),
166 'version': build_version.ChromeVersionNoTrunk(),
167 'min_chrome_version': desc.get('MIN_CHROME_VERSION')
169 RunTemplateFileIfChanged(srcpath, dstpath, replace)
172 def FindAndCopyFiles(src_files, root, search_dirs, dst_dir):
173 buildbot_common.MakeDir(dst_dir)
174 for src_name in src_files:
175 src_file = FindFile(src_name, root, search_dirs)
176 if not src_file:
177 ErrorExit('Failed to find: ' + src_name)
178 dst_file = os.path.join(dst_dir, src_name)
179 if os.path.exists(dst_file):
180 if os.stat(src_file).st_mtime <= os.stat(dst_file).st_mtime:
181 Trace('Skipping "%s", destination "%s" is newer.' % (
182 src_file, dst_file))
183 continue
184 dst_path = os.path.dirname(dst_file)
185 if not os.path.exists(dst_path):
186 buildbot_common.MakeDir(dst_path)
187 buildbot_common.CopyFile(src_file, dst_file)
190 def ModifyDescInPlace(desc):
191 """Perform post-load processing on .dsc file data.
193 Currently this consists of:
194 - Add -Wall to CXXFLAGS
197 for target in desc['TARGETS']:
198 target.setdefault('CXXFLAGS', [])
199 target['CXXFLAGS'].insert(0, '-Wall')
202 def ProcessProject(pepperdir, srcroot, dstroot, desc, toolchains, configs=None,
203 first_toolchain=False):
204 if not configs:
205 configs = ['Debug', 'Release']
207 name = desc['NAME']
208 out_dir = os.path.join(dstroot, desc['DEST'], name)
209 buildbot_common.MakeDir(out_dir)
210 srcdirs = desc.get('SEARCH', ['.', SDK_RESOURCE_DIR])
212 # Copy sources to example directory
213 sources = GenerateSourceCopyList(desc)
214 FindAndCopyFiles(sources, srcroot, srcdirs, out_dir)
216 # Copy public headers to the include directory.
217 for headers_set in desc.get('HEADERS', []):
218 headers = headers_set['FILES']
219 header_out_dir = os.path.join(dstroot, headers_set['DEST'])
220 FindAndCopyFiles(headers, srcroot, srcdirs, header_out_dir)
222 make_path = os.path.join(out_dir, 'Makefile')
224 outdir = os.path.dirname(os.path.abspath(make_path))
225 if getos.GetPlatform() == 'win':
226 AddMakeBat(pepperdir, outdir)
228 # If this project has no TARGETS, then we don't need to generate anything.
229 if 'TARGETS' not in desc:
230 return (name, desc['DEST'])
232 if IsNexe(desc):
233 template = os.path.join(SDK_RESOURCE_DIR, 'Makefile.example.template')
234 else:
235 template = os.path.join(SDK_RESOURCE_DIR, 'Makefile.library.template')
237 # Ensure the order of |tools| is the same as toolchains; that way if
238 # first_toolchain is set, it will choose based on the order of |toolchains|.
239 tools = [tool for tool in toolchains if tool in desc['TOOLS']]
240 if first_toolchain:
241 tools = [tools[0]]
243 ModifyDescInPlace(desc)
245 template_dict = {
246 'desc': desc,
247 'rel_sdk': '/'.join(['..'] * (len(desc['DEST'].split('/')) + 1)),
248 'pre': desc.get('PRE', ''),
249 'post': desc.get('POST', ''),
250 'tools': tools,
251 'sel_ldr': desc.get('SEL_LDR'),
252 'targets': desc['TARGETS'],
253 'multi_platform': desc.get('MULTI_PLATFORM', False),
255 RunTemplateFileIfChanged(template, make_path, template_dict)
257 if IsExample(desc):
258 ProcessHTML(srcroot, dstroot, desc, toolchains, configs,
259 first_toolchain)
260 if not desc.get('NO_PACKAGE_FILES'):
261 GenerateManifest(srcroot, dstroot, desc)
263 return (name, desc['DEST'])
266 def GenerateMasterMakefile(pepperdir, out_path, targets, deps):
267 """Generate a Master Makefile that builds all examples.
269 Args:
270 pepperdir: NACL_SDK_ROOT
271 out_path: Root for output such that out_path+NAME = full path
272 targets: List of targets names
274 in_path = os.path.join(SDK_RESOURCE_DIR, 'Makefile.index.template')
275 out_path = os.path.join(out_path, 'Makefile')
276 rel_path = os.path.relpath(pepperdir, os.path.dirname(out_path))
277 template_dict = {
278 'projects': targets,
279 'deps' : deps,
280 'rel_sdk' : rel_path,
282 RunTemplateFileIfChanged(in_path, out_path, template_dict)
283 outdir = os.path.dirname(os.path.abspath(out_path))
284 if getos.GetPlatform() == 'win':
285 AddMakeBat(pepperdir, outdir)