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.
12 from buildbot_common import ErrorExit
13 from easy_template import RunTemplateFileIfChanged
14 from build_paths import SDK_RESOURCE_DIR
18 sys.stderr.write(str(msg) + '\n')
24 return dest.startswith(('examples', 'tests', 'getting_started'))
27 def GenerateSourceCopyList(desc):
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', []))
42 sources.append('common.js')
43 if not desc.get('NO_PACKAGE_FILES'):
44 sources.extend(['icon128.png', 'background.js'])
49 def GetSourcesDict(sources):
51 for key in ['.c', '.cc']:
52 source_list = [fname for fname in sources if fname.endswith(key)]
54 source_map[key] = source_list
60 def GetProjectObjects(source_dict):
62 for key in ['.c', '.cc']:
63 for src in source_dict[key]:
64 object_list.append(os.path.splitext(src)[0])
68 def GetPlatforms(plat_list, plat_filter, first_toolchain):
70 for plat in plat_list:
71 if plat in plat_filter:
72 platforms.append(plat)
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)
105 def FindFile(name, srcroot, srcdirs):
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):
113 checks.append(srcfile)
115 ErrorMsgFunc('%s not found in:\n\t%s' % (name, '\n\t'.join(checks)))
120 for target in desc['TARGETS']:
121 if target['TYPE'] == 'main':
126 def ProcessHTML(srcroot, dstroot, desc, toolchains, configs, first_toolchain):
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}"
137 'title': desc['TITLE'],
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 socket_permissions = desc.get('SOCKET_PERMISSIONS', [])
151 combined_permissions = list(permissions)
152 if socket_permissions:
153 combined_permissions.append({'socket': socket_permissions})
154 pretty_permissions = json.dumps(combined_permissions,
155 sort_keys=True, indent=4)
157 'name': desc['TITLE'],
158 'description': '%s Example' % desc['TITLE'],
161 'permissions': pretty_permissions,
162 'version': build_version.ChromeVersionNoTrunk()
164 RunTemplateFileIfChanged(srcpath, dstpath, replace)
167 def FindAndCopyFiles(src_files, root, search_dirs, dst_dir):
168 buildbot_common.MakeDir(dst_dir)
169 for src_name in src_files:
170 src_file = FindFile(src_name, root, search_dirs)
172 ErrorExit('Failed to find: ' + src_name)
173 dst_file = os.path.join(dst_dir, src_name)
174 if os.path.exists(dst_file):
175 if os.stat(src_file).st_mtime <= os.stat(dst_file).st_mtime:
176 Trace('Skipping "%s", destination "%s" is newer.' % (
179 dst_path = os.path.dirname(dst_file)
180 if not os.path.exists(dst_path):
181 buildbot_common.MakeDir(dst_path)
182 buildbot_common.CopyFile(src_file, dst_file)
185 def ModifyDescInPlace(desc):
186 """Perform post-load processing on .dsc file data.
188 Currently this consists of:
189 - Add -Wall to CXXFLAGS
190 - Synthesize SEL_LDR_LIBS and SEL_LDR_DEPS by stripping
191 down LIBS and DEPS (removing certain ppapi-only libs).
194 ppapi_only_libs = ['ppapi_simple']
196 for target in desc['TARGETS']:
197 target.setdefault('CXXFLAGS', [])
198 target['CXXFLAGS'].insert(0, '-Wall')
201 value = target.get(key, [])
202 if type(value) == dict:
204 for key in value.keys():
205 value[key] = [v for v in value[key] if v not in ppapi_only_libs]
207 value = [v for v in value if v not in ppapi_only_libs]
210 target['SEL_LDR_LIBS'] = filter_out('LIBS')
211 target['SEL_LDR_DEPS'] = filter_out('DEPS')
214 def ProcessProject(pepperdir, srcroot, dstroot, desc, toolchains, configs=None,
215 first_toolchain=False):
217 configs = ['Debug', 'Release']
220 out_dir = os.path.join(dstroot, desc['DEST'], name)
221 buildbot_common.MakeDir(out_dir)
222 srcdirs = desc.get('SEARCH', ['.', SDK_RESOURCE_DIR])
224 # Copy sources to example directory
225 sources = GenerateSourceCopyList(desc)
226 FindAndCopyFiles(sources, srcroot, srcdirs, out_dir)
228 # Copy public headers to the include directory.
229 for headers_set in desc.get('HEADERS', []):
230 headers = headers_set['FILES']
231 header_out_dir = os.path.join(dstroot, headers_set['DEST'])
232 FindAndCopyFiles(headers, srcroot, srcdirs, header_out_dir)
234 make_path = os.path.join(out_dir, 'Makefile')
236 outdir = os.path.dirname(os.path.abspath(make_path))
237 if getos.GetPlatform() == 'win':
238 AddMakeBat(pepperdir, outdir)
240 # If this project has no TARGETS, then we don't need to generate anything.
241 if 'TARGETS' not in desc:
242 return (name, desc['DEST'])
245 template = os.path.join(SDK_RESOURCE_DIR, 'Makefile.example.template')
247 template = os.path.join(SDK_RESOURCE_DIR, 'Makefile.library.template')
249 # Ensure the order of |tools| is the same as toolchains; that way if
250 # first_toolchain is set, it will choose based on the order of |toolchains|.
251 tools = [tool for tool in toolchains if tool in desc['TOOLS']]
255 ModifyDescInPlace(desc)
259 'rel_sdk': '/'.join(['..'] * (len(desc['DEST'].split('/')) + 1)),
260 'pre': desc.get('PRE', ''),
261 'post': desc.get('POST', ''),
263 'sel_ldr': desc.get('SEL_LDR'),
264 'targets': desc['TARGETS'],
266 RunTemplateFileIfChanged(template, make_path, template_dict)
269 ProcessHTML(srcroot, dstroot, desc, toolchains, configs,
271 if not desc.get('NO_PACKAGE_FILES'):
272 GenerateManifest(srcroot, dstroot, desc)
274 return (name, desc['DEST'])
277 def GenerateMasterMakefile(pepperdir, out_path, targets):
278 """Generate a Master Makefile that builds all examples.
281 pepperdir: NACL_SDK_ROOT
282 out_path: Root for output such that out_path+NAME = full path
283 targets: List of targets names
285 in_path = os.path.join(SDK_RESOURCE_DIR, 'Makefile.index.template')
286 out_path = os.path.join(out_path, 'Makefile')
287 rel_path = os.path.relpath(pepperdir, os.path.dirname(out_path))
290 'rel_sdk' : rel_path,
292 RunTemplateFileIfChanged(in_path, out_path, template_dict)
293 outdir = os.path.dirname(os.path.abspath(out_path))
294 if getos.GetPlatform() == 'win':
295 AddMakeBat(pepperdir, outdir)