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 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)
160 'name': desc
['TITLE'],
161 'description': '%s Example' % desc
['TITLE'],
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
)
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.' % (
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):
205 configs
= ['Debug', 'Release']
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'])
233 template
= os
.path
.join(SDK_RESOURCE_DIR
, 'Makefile.example.template')
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']]
243 ModifyDescInPlace(desc
)
247 'rel_sdk': '/'.join(['..'] * (len(desc
['DEST'].split('/')) + 1)),
248 'pre': desc
.get('PRE', ''),
249 'post': desc
.get('POST', ''),
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
)
258 ProcessHTML(srcroot
, dstroot
, desc
, toolchains
, configs
,
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.
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
))
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
)