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 'multi_platform': desc
.get('MULTI_PLATFORM', False),
163 'version': build_version
.ChromeVersionNoTrunk(),
164 'min_chrome_version': desc
.get('MIN_CHROME_VERSION')
166 RunTemplateFileIfChanged(srcpath
, dstpath
, replace
)
169 def FindAndCopyFiles(src_files
, root
, search_dirs
, dst_dir
):
170 buildbot_common
.MakeDir(dst_dir
)
171 for src_name
in src_files
:
172 src_file
= FindFile(src_name
, root
, search_dirs
)
174 ErrorExit('Failed to find: ' + src_name
)
175 dst_file
= os
.path
.join(dst_dir
, src_name
)
176 if os
.path
.exists(dst_file
):
177 if os
.stat(src_file
).st_mtime
<= os
.stat(dst_file
).st_mtime
:
178 Trace('Skipping "%s", destination "%s" is newer.' % (
181 dst_path
= os
.path
.dirname(dst_file
)
182 if not os
.path
.exists(dst_path
):
183 buildbot_common
.MakeDir(dst_path
)
184 buildbot_common
.CopyFile(src_file
, dst_file
)
187 def ModifyDescInPlace(desc
):
188 """Perform post-load processing on .dsc file data.
190 Currently this consists of:
191 - Add -Wall to CXXFLAGS
192 - Synthesize SEL_LDR_LIBS and SEL_LDR_DEPS by stripping
193 down LIBS and DEPS (removing certain ppapi-only libs).
196 ppapi_only_libs
= ['ppapi_simple']
198 for target
in desc
['TARGETS']:
199 target
.setdefault('CXXFLAGS', [])
200 target
['CXXFLAGS'].insert(0, '-Wall')
203 value
= target
.get(key
, [])
204 if type(value
) == dict:
206 for key
in value
.keys():
207 value
[key
] = [v
for v
in value
[key
] if v
not in ppapi_only_libs
]
209 value
= [v
for v
in value
if v
not in ppapi_only_libs
]
212 target
['SEL_LDR_LIBS'] = filter_out('LIBS')
213 target
['SEL_LDR_DEPS'] = filter_out('DEPS')
216 def ProcessProject(pepperdir
, srcroot
, dstroot
, desc
, toolchains
, configs
=None,
217 first_toolchain
=False):
219 configs
= ['Debug', 'Release']
222 out_dir
= os
.path
.join(dstroot
, desc
['DEST'], name
)
223 buildbot_common
.MakeDir(out_dir
)
224 srcdirs
= desc
.get('SEARCH', ['.', SDK_RESOURCE_DIR
])
226 # Copy sources to example directory
227 sources
= GenerateSourceCopyList(desc
)
228 FindAndCopyFiles(sources
, srcroot
, srcdirs
, out_dir
)
230 # Copy public headers to the include directory.
231 for headers_set
in desc
.get('HEADERS', []):
232 headers
= headers_set
['FILES']
233 header_out_dir
= os
.path
.join(dstroot
, headers_set
['DEST'])
234 FindAndCopyFiles(headers
, srcroot
, srcdirs
, header_out_dir
)
236 make_path
= os
.path
.join(out_dir
, 'Makefile')
238 outdir
= os
.path
.dirname(os
.path
.abspath(make_path
))
239 if getos
.GetPlatform() == 'win':
240 AddMakeBat(pepperdir
, outdir
)
242 # If this project has no TARGETS, then we don't need to generate anything.
243 if 'TARGETS' not in desc
:
244 return (name
, desc
['DEST'])
247 template
= os
.path
.join(SDK_RESOURCE_DIR
, 'Makefile.example.template')
249 template
= os
.path
.join(SDK_RESOURCE_DIR
, 'Makefile.library.template')
251 # Ensure the order of |tools| is the same as toolchains; that way if
252 # first_toolchain is set, it will choose based on the order of |toolchains|.
253 tools
= [tool
for tool
in toolchains
if tool
in desc
['TOOLS']]
257 ModifyDescInPlace(desc
)
261 'rel_sdk': '/'.join(['..'] * (len(desc
['DEST'].split('/')) + 1)),
262 'pre': desc
.get('PRE', ''),
263 'post': desc
.get('POST', ''),
265 'sel_ldr': desc
.get('SEL_LDR'),
266 'targets': desc
['TARGETS'],
267 'multi_platform': desc
.get('MULTI_PLATFORM', False),
269 RunTemplateFileIfChanged(template
, make_path
, template_dict
)
272 ProcessHTML(srcroot
, dstroot
, desc
, toolchains
, configs
,
274 if not desc
.get('NO_PACKAGE_FILES'):
275 GenerateManifest(srcroot
, dstroot
, desc
)
277 return (name
, desc
['DEST'])
280 def GenerateMasterMakefile(pepperdir
, out_path
, targets
, deps
):
281 """Generate a Master Makefile that builds all examples.
284 pepperdir: NACL_SDK_ROOT
285 out_path: Root for output such that out_path+NAME = full path
286 targets: List of targets names
288 in_path
= os
.path
.join(SDK_RESOURCE_DIR
, 'Makefile.index.template')
289 out_path
= os
.path
.join(out_path
, 'Makefile')
290 rel_path
= os
.path
.relpath(pepperdir
, os
.path
.dirname(out_path
))
294 'rel_sdk' : rel_path
,
296 RunTemplateFileIfChanged(in_path
, out_path
, template_dict
)
297 outdir
= os
.path
.dirname(os
.path
.abspath(out_path
))
298 if getos
.GetPlatform() == 'win':
299 AddMakeBat(pepperdir
, outdir
)