Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(267)

Side by Side Diff: native_client_sdk/src/build_tools/generate_make.py

Issue 10828187: [NaCl SDK] Support multiple configs (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 import buildbot_common 6 import buildbot_common
7 import make_rules 7 import make_rules
8 import optparse 8 import optparse
9 import os 9 import os
10 import sys 10 import sys
11 11
12 from make_rules import BuildDefineList, BuildLibList, BuildToolDict 12 from make_rules import MakeRules, SetVar, GenerateCleanRules, GenerateNMFRules
13 from make_rules import BuildIncludeList, GetBuildRule, BUILD_RULES
14 13
15 SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) 14 SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
16 SDK_SRC_DIR = os.path.dirname(SCRIPT_DIR) 15 SDK_SRC_DIR = os.path.dirname(SCRIPT_DIR)
17 SDK_EXAMPLE_DIR = os.path.join(SDK_SRC_DIR, 'examples') 16 SDK_EXAMPLE_DIR = os.path.join(SDK_SRC_DIR, 'examples')
18 SDK_DIR = os.path.dirname(SDK_SRC_DIR) 17 SDK_DIR = os.path.dirname(SDK_SRC_DIR)
19 SRC_DIR = os.path.dirname(SDK_DIR) 18 SRC_DIR = os.path.dirname(SDK_DIR)
20 OUT_DIR = os.path.join(SRC_DIR, 'out') 19 OUT_DIR = os.path.join(SRC_DIR, 'out')
21 PPAPI_DIR = os.path.join(SRC_DIR, 'ppapi') 20 PPAPI_DIR = os.path.join(SRC_DIR, 'ppapi')
22 21
23 # Add SDK make tools scripts to the python path. 22 # Add SDK make tools scripts to the python path.
24 sys.path.append(os.path.join(SDK_SRC_DIR, 'tools')) 23 sys.path.append(os.path.join(SDK_SRC_DIR, 'tools'))
25 import getos 24 import getos
26 25
27 SUPPORTED_HOSTS = ['win']
28 26
29 def ErrorExit(text): 27 def ErrorExit(text):
30 ErrorMsgFunc(text) 28 ErrorMsgFunc(text)
31 sys.exit(1) 29 sys.exit(1)
32 30
33 31
34 def Replace(text, replacements): 32 def Replace(text, replacements):
35 for key in replacements: 33 for key in replacements:
36 val = replacements[key] 34 val = replacements[key]
37 if val is not None: 35 if val is not None:
38 text = text.replace(key, val) 36 text = text.replace(key, val)
39 return text 37 return text
40 38
41 39
42 def WriteReplaced(srcpath, dstpath, replacements): 40 def WriteReplaced(srcpath, dstpath, replacements):
43 text = open(srcpath, 'rb').read() 41 text = open(srcpath, 'rb').read()
44 text = Replace(text, replacements) 42 text = Replace(text, replacements)
45 open(dstpath, 'wb').write(text) 43 open(dstpath, 'wb').write(text)
46 44
47 45
48 def SetVar(varname, values):
49 if not values:
50 return varname + ':=\n'
51
52 line = varname + ':='
53 out = ''
54 for value in values:
55 if len(line) + len(value) > 78:
56 out += line[:-1] + '\n'
57 line = '%s+=%s ' % (varname, value)
58 else:
59 line += value + ' '
60
61 if line:
62 out += line[:-1] + '\n'
63 return out
64
65
66 def GenerateSourceCopyList(desc): 46 def GenerateSourceCopyList(desc):
67 sources = [] 47 sources = []
68 # Add sources for each target 48 # Add sources for each target
69 for target in desc['TARGETS']: 49 for target in desc['TARGETS']:
70 sources.extend(target['SOURCES']) 50 sources.extend(target['SOURCES'])
71 51
72 # And HTML and data files 52 # And HTML and data files
73 sources.extend(desc.get('DATA', [])) 53 sources.extend(desc.get('DATA', []))
74 54
75 if desc['DEST'] == 'examples': 55 if desc['DEST'] == 'examples':
76 sources.append('common.js') 56 sources.append('common.js')
77 57
78 return sources 58 return sources
79 59
80 60
81 def GetSourcesDict(sources): 61 def GetSourcesDict(sources):
82 source_map = {} 62 source_map = {}
83 for key in ['.c', '.cc']: 63 for key in ['.c', '.cc']:
84 source_list = [fname for fname in sources if fname.endswith(key)] 64 source_list = [fname for fname in sources if fname.endswith(key)]
85 if source_list: 65 if source_list:
86 source_map[key] = source_list 66 source_map[key] = source_list
87 else: 67 else:
88 source_map[key] = [] 68 source_map[key] = []
89 return source_map 69 return source_map
90 70
91 71
72 def GetProjectObjects(source_dict):
73 object_list = []
74 for key in ['.c', '.cc']:
75 for src in source_dict[key]:
76 object_list.append(os.path.splitext(src)[0])
77 return object_list
78
79
92 def GetPlatforms(plat_list, plat_filter): 80 def GetPlatforms(plat_list, plat_filter):
93 platforms = [] 81 platforms = []
94 for plat in plat_list: 82 for plat in plat_list:
95 if plat in plat_filter: 83 if plat in plat_filter:
96 platforms.append(plat) 84 platforms.append(plat)
97 return platforms 85 return platforms
98 86
99 87
100 def GenerateToolDefaults(desc, tools): 88 def GenerateToolDefaults(desc, tools):
101 defaults = '' 89 defaults = ''
102 for tool in tools: 90 for tool in tools:
103 defaults += BUILD_RULES[tool]['DEFS'] 91 defaults += MakeRules(tool).BuildDefaults()
104 return defaults 92 return defaults
105 93
106 94
107 def GenerateSettings(desc, tools): 95 def GenerateSettings(desc, tools):
108 settings = SetVar('VALID_TOOLCHAINS', tools) 96 settings = SetVar('VALID_TOOLCHAINS', tools)
109 settings+= 'TOOLCHAIN?=%s\n\n' % tools[0] 97 settings+= 'TOOLCHAIN?=%s\n\n' % tools[0]
110 for target in desc['TARGETS']: 98 for target in desc['TARGETS']:
111 name = target['NAME'] 99 project = target['NAME']
112 macro = name.upper() 100 macro = project.upper()
113 srcs = GetSourcesDict(target['SOURCES']) 101 srcs = GetSourcesDict(target['SOURCES'])
114 102
115 if srcs['.c']: 103 c_flags = target.get('CCFLAGS')
116 flags = target.get('CCFLAGS', ['$(NACL_CCFLAGS)']) 104 cc_flags = target.get('CXXFLAGS')
117 settings += SetVar(macro + '_CC', srcs['.c']) 105 ld_flags = target.get('LDFLAGS')
118 settings += SetVar(macro + '_CCFLAGS', flags)
119 106
120 if srcs['.cc']: 107 if c_flags:
121 flags = target.get('CXXFLAGS', ['$(NACL_CXXFLAGS)']) 108 settings += SetVar(macro + '_CCFLAGS', c_flags)
122 settings += SetVar(macro + '_CXX', srcs['.cc']) 109 if cc_flags:
123 settings += SetVar(macro + '_CXXFLAGS', flags) 110 settings += SetVar(macro + '_CXXFLAGS', cc_flags)
124 111 if ld_flags:
125 flags = target.get('LDFLAGS', ['$(NACL_LDFLAGS)']) 112 settings += SetVar(macro + '_LDFLAGS', ld_flags)
126 settings += SetVar(macro + '_LDFLAGS', flags)
127 return settings 113 return settings
128 114
129 115
130 def GetTarget(tool, targ_type, replace):
131 pattern = BUILD_RULES[tool]['TOOL'][targ_type]
132 return Replace(pattern, replace)
133
134
135 def GenerateCompile(target, tool, arch, srcs):
136 """Generates a Compile target.
137
138 For the given target, toolset and architecture, returns a rule to generate
139 the object files for the set of sources.
140
141 Returns:
142 Returns a tuple containin the objects and the rule.
143 """
144 rules = ''
145 name = target['NAME']
146 object_sets = []
147
148 defs = BuildDefineList(tool, target.get('DEFINES', []))
149 includes = BuildIncludeList(tool, target.get('INCLUDES', []))
150
151 if srcs['.c']:
152 replace = BuildToolDict(tool, name, arch, 'c',
153 DEFLIST=defs, INCLUDELIST=includes)
154 compile_rule = GetBuildRule(tool, 'CC')
155 rules += Replace(compile_rule, replace)
156 object_sets.append('$(%s)' % replace['<OBJS>'])
157
158 if srcs['.cc']:
159 replace = BuildToolDict(tool, name, arch, 'cc',
160 DEFLIST=defs, INCLUDELIST=includes)
161 compile_rule = GetBuildRule(tool, 'CXX')
162 rules += Replace(compile_rule, replace)
163 object_sets.append('$(%s)' % replace['<OBJS>'])
164
165 return (' '.join(object_sets), rules)
166
167
168 def GenerateLink(target, tool, arch, objs):
169 """Generate a Link target.
170
171 Returns:
172 Returns a tuple containing the rule and target.
173 """
174 targ_type = target['TYPE']
175 link_rule = GetBuildRule(tool, targ_type.upper())
176 libs = target.get('LIBS', [])
177 libs = BuildLibList(tool, libs)
178 replace = BuildToolDict(tool, target['NAME'], arch, 'nexe',
179 OBJS=objs, LIBLIST=libs)
180 rule = Replace(link_rule, replace)
181 target_out = GetTarget(tool, targ_type, replace)
182 return target_out, rule
183
184
185 def GenerateNMF(target, tool):
186 nmf_rule = BUILD_RULES[tool]['NMF']
187 replace = BuildToolDict(tool, target['NAME'])
188 rule = Replace(nmf_rule, replace)
189 target_out = GetTarget(tool, 'nmf', replace)
190 return target_out, rule
191
192
193 def GenerateRules(desc, tools): 116 def GenerateRules(desc, tools):
194 all_targets = [] 117 all_targets = []
195 rules = ''
196 clean = [] 118 clean = []
119 rules = '#\n# Per target object lists\n#\n'
120
121 #Determine which projects are in the NMF files.
122 main = None
123 dlls = []
124 project_list = []
125 glibc_rename = []
126
127 for target in desc['TARGETS']:
128 ptype = target['TYPE'].upper()
129 project = target['NAME']
130 project_list.append(project)
131 srcs = GetSourcesDict(target['SOURCES'])
132 if ptype == 'MAIN':
133 main = project
134 if ptype == 'SO':
135 dlls.append(project)
136 for arch in ['x86_32', 'x86_64']:
137 glibc_rename.append('-n %s_%s.so,%s.so' % (project, arch, project))
138
139 objects = GetProjectObjects(srcs)
140 rules += SetVar('%s_OBJS' % project.upper(), objects)
141 if glibc_rename:
142 rules += SetVar('GLIBC_REMAP', glibc_rename)
143
144 configs = desc.get('CONFIGS', ['Debug', 'Release'])
197 for tc in tools: 145 for tc in tools:
198 rules += '\n#\n# Rules for %s toolchain\n#\n%s:\n\t$(MKDIR) %s\n' % ( 146 makeobj = MakeRules(tc)
199 tc, tc, tc) 147 arches = makeobj.GetArches()
200 main = None 148 rules += makeobj.BuildDirectoryRules(configs)
201 for target in desc['TARGETS']: 149 for cfg in configs:
202 name = target['NAME'] 150 makeobj.SetConfig(cfg)
203 srcs = GetSourcesDict(target['SOURCES']) 151 for target in desc['TARGETS']:
204 for arch in BUILD_RULES[tc]['ARCHES']: 152 project = target['NAME']
205 objs, comp_rule = GenerateCompile(target, tc, arch, srcs) 153 ptype = target['TYPE']
206 targs, link_rule = GenerateLink(target, tc, arch, objs) 154 srcs = GetSourcesDict(target['SOURCES'])
207 rules += comp_rule + link_rule 155 objs = GetProjectObjects(srcs)
208 clean.append(objs) 156 defs = target.get('DEFINES', [])
209 if target['TYPE'] == 'lib': 157 incs = target.get('INCLUDES', [])
210 all_targets.append(targs) 158 libs = target.get('LIBS', [])
159 lpaths = target.get('LIBPATHS', [])
160 ipaths = target.get('INCPATHS', [])
161 makeobj.SetProject(project, ptype, defs=defs, incs=incs, libs=libs)
162 for arch in arches:
163 makeobj.SetArch(arch)
164 for src in srcs.get('.c', []):
165 rules += makeobj.BuildCompileRule('CC', src)
166 for src in srcs.get('.cc', []):
167 rules += makeobj.BuildCompileRule('CXX', src)
168 rules += '\n'
169 rules += makeobj.BuildObjectList()
170 rules += makeobj.BuildLinkRule()
171 if main:
172 rules += GenerateNMFRules(tc, main, dlls, cfg, arches)
211 173
212 if target['TYPE'] == 'main': 174 rules += GenerateCleanRules(tools, configs)
213 main = target 175 rules += '\nall: $(ALL_TARGETS)\n'
176 return '', rules
214 177
215 if main:
216 targs, nmf_rule = GenerateNMF(main, tc)
217 rules += nmf_rule
218 all_targets.append(targs)
219 rules += '\n.PHONY : clean\nclean:\n\t$(RM) $(DEPFILES) ' + ' '.join(clean)
220 rules += '\n\n-include $(DEPFILES)'
221 return ' '.join(all_targets), rules
222
223
224 def GenerateTargets(desc, tools):
225 targets = []
226 rules = ''
227 for tc in tools:
228 for target in desc['TARGETS']:
229 name = target['NAME']
230 replace = BuildToolDict(tc, name)
231 target = GetTarget(tc, target['TYPE'], replace)
232 if target:
233 targets.append(target)
234 return targets
235 178
236 179
237 def GenerateReplacements(desc, tools): 180 def GenerateReplacements(desc, tools):
238 # Generate target settings 181 # Generate target settings
239 plats = GetPlatforms(desc['TOOLS'], tools) 182 plats = GetPlatforms(desc['TOOLS'], tools)
240 183
241 settings = GenerateSettings(desc, tools) 184 settings = GenerateSettings(desc, tools)
242 tool_def = GenerateToolDefaults(desc, tools) 185 tool_def = GenerateToolDefaults(desc, tools)
243 all_targets, rules = GenerateRules(desc, tools) 186 all_targets, rules = GenerateRules(desc, tools)
244 187
245 prelaunch = desc.get('LAUNCH', '') 188 prelaunch = desc.get('LAUNCH', '')
246 prerun = desc.get('PRE', '') 189 prerun = desc.get('PRE', '')
247 postlaunch = desc.get('POST', '') 190 postlaunch = desc.get('POST', '')
248 191
249 targets = GenerateTargets(desc, tools) 192 target_def = 'all:'
250 target_def = 'all: ' + all_targets
251 193
252 return { 194 return {
253 '__PROJECT_SETTINGS__' : settings, 195 '__PROJECT_SETTINGS__' : settings,
254 '__PROJECT_TARGETS__' : target_def, 196 '__PROJECT_TARGETS__' : target_def,
255 '__PROJECT_TOOLS__' : tool_def, 197 '__PROJECT_TOOLS__' : tool_def,
256 '__PROJECT_RULES__' : rules, 198 '__PROJECT_RULES__' : rules,
257 '__PROJECT_PRELAUNCH__' : prelaunch, 199 '__PROJECT_PRELAUNCH__' : prelaunch,
258 '__PROJECT_PRERUN__' : prerun, 200 '__PROJECT_PRERUN__' : prerun,
259 '__PROJECT_POSTLAUNCH__' : postlaunch 201 '__PROJECT_POSTLAUNCH__' : postlaunch
260 } 202 }
261 203
262 204
263 # 'KEY' : ( <TYPE>, [Accepted Values], <Required?>) 205 # 'KEY' : ( <TYPE>, [Accepted Values], <Required?>)
264 DSC_FORMAT = { 206 DSC_FORMAT = {
265 'TOOLS' : (list, ['newlib', 'glibc', 'pnacl', 'win'], True), 207 'TOOLS' : (list, ['newlib', 'glibc', 'pnacl', 'win'], True),
208 'CONFIGS' : (list, ['Debug', 'Release'], False),
266 'PREREQ' : (list, '', False), 209 'PREREQ' : (list, '', False),
267 'TARGETS' : (list, { 210 'TARGETS' : (list, {
268 'NAME': (str, '', True), 211 'NAME': (str, '', True),
269 'TYPE': (str, ['main', 'nexe', 'lib', 'so'], True), 212 'TYPE': (str, ['main', 'nexe', 'lib', 'so'], True),
270 'SOURCES': (list, '', True), 213 'SOURCES': (list, '', True),
271 'CCFLAGS': (list, '', False), 214 'CCFLAGS': (list, '', False),
272 'CXXFLAGS': (list, '', False), 215 'CXXFLAGS': (list, '', False),
273 'LDFLAGS': (list, '', False), 216 'LDFLAGS': (list, '', False),
274 'INCLUDES': (list, '', False), 217 'INCLUDES': (list, '', False),
275 'LIBS' : (list, '', False) 218 'LIBS' : (list, '', False)
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
410 def IsNexe(desc): 353 def IsNexe(desc):
411 for target in desc['TARGETS']: 354 for target in desc['TARGETS']:
412 if target['TYPE'] == 'main': 355 if target['TYPE'] == 'main':
413 return True 356 return True
414 return False 357 return False
415 358
416 359
417 def ProcessHTML(srcroot, dstroot, desc, toolchains): 360 def ProcessHTML(srcroot, dstroot, desc, toolchains):
418 name = desc['NAME'] 361 name = desc['NAME']
419 outdir = os.path.join(dstroot, desc['DEST'], name) 362 outdir = os.path.join(dstroot, desc['DEST'], name)
420
421 srcfile = os.path.join(srcroot, 'index.html') 363 srcfile = os.path.join(srcroot, 'index.html')
422 tools = GetPlatforms(toolchains, desc['TOOLS']) 364 tools = GetPlatforms(toolchains, desc['TOOLS'])
365
366 configs = ['Debug', 'Release']
367
423 for tool in tools: 368 for tool in tools:
424 dstfile = os.path.join(outdir, 'index_%s.html' % tool); 369 for cfg in configs:
425 print 'Writting from %s to %s' % (srcfile, dstfile) 370 dstfile = os.path.join(outdir, 'index_%s_%s.html' % (tool, cfg))
426 replace = { 371 print 'Writing from %s to %s' % (srcfile, dstfile)
427 '<NAME>': name, 372 replace = {
428 '<TITLE>': desc['TITLE'], 373 '<config>': cfg,
429 '<tc>': tool 374 '<NAME>': name,
430 } 375 '<TITLE>': desc['TITLE'],
431 WriteReplaced(srcfile, dstfile, replace) 376 '<tc>': tool
377 }
378 WriteReplaced(srcfile, dstfile, replace)
432 379
433 replace['<tc>'] = tools[0] 380 replace['<tc>'] = tools[0]
381 replace['<config>'] = configs[0]
382
434 srcfile = os.path.join(SDK_SRC_DIR, 'build_tools', 'redirect.html') 383 srcfile = os.path.join(SDK_SRC_DIR, 'build_tools', 'redirect.html')
435 dstfile = os.path.join(outdir, 'index.html') 384 dstfile = os.path.join(outdir, 'index.html')
436 WriteReplaced(srcfile, dstfile, replace) 385 WriteReplaced(srcfile, dstfile, replace)
437 386
438 387
439 def LoadProject(filename, toolchains): 388 def LoadProject(filename, toolchains):
440 """Generate a Master Makefile that builds all examples. 389 """Generate a Master Makefile that builds all examples.
441 390
442 Load a project desciption file, verifying it conforms and checking 391 Load a project desciption file, verifying it conforms and checking
443 if it matches the set of requested toolchains. Return None if the 392 if it matches the set of requested toolchains. Return None if the
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
553 502
554 if not args: 503 if not args:
555 ErrorExit('Please specify one or more projects to generate Makefiles for.') 504 ErrorExit('Please specify one or more projects to generate Makefiles for.')
556 505
557 # By default support newlib and glibc 506 # By default support newlib and glibc
558 if not toolchains: 507 if not toolchains:
559 toolchains = ['newlib', 'glibc'] 508 toolchains = ['newlib', 'glibc']
560 print 'Using default toolchains: ' + ' '.join(toolchains) 509 print 'Using default toolchains: ' + ' '.join(toolchains)
561 510
562 master_projects = {} 511 master_projects = {}
512
563 for filename in args: 513 for filename in args:
564 desc = LoadProject(filename, toolchains) 514 desc = LoadProject(filename, toolchains)
565 if not desc: 515 if not desc:
566 print 'Skipping %s, not in [%s].' % (filename, ', '.join(toolchains)) 516 print 'Skipping %s, not in [%s].' % (filename, ', '.join(toolchains))
567 continue 517 continue
568 518
569 if desc.get('EXPERIMENTAL', False) and not options.experimental: 519 if desc.get('EXPERIMENTAL', False) and not options.experimental:
570 print 'Skipping %s, experimental only.' % (filename,) 520 print 'Skipping %s, experimental only.' % (filename,)
571 continue 521 continue
572 522
(...skipping 12 matching lines...) Expand all
585 if options.master: 535 if options.master:
586 master_in = os.path.join(SDK_EXAMPLE_DIR, 'Makefile') 536 master_in = os.path.join(SDK_EXAMPLE_DIR, 'Makefile')
587 for dest, projects in master_projects.iteritems(): 537 for dest, projects in master_projects.iteritems():
588 master_out = os.path.join(options.dstroot, dest, 'Makefile') 538 master_out = os.path.join(options.dstroot, dest, 'Makefile')
589 GenerateMasterMakefile(master_in, master_out, projects) 539 GenerateMasterMakefile(master_in, master_out, projects)
590 return 0 540 return 0
591 541
592 542
593 if __name__ == '__main__': 543 if __name__ == '__main__':
594 sys.exit(main(sys.argv[1:])) 544 sys.exit(main(sys.argv[1:]))
OLDNEW
« no previous file with comments | « native_client_sdk/src/build_tools/build_sdk.py ('k') | native_client_sdk/src/build_tools/make_rules.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698