Commit 7446d88f authored by binji@chromium.org's avatar binji@chromium.org

[NaCl SDK] Support multiple configs

Slightly modified from noelallen's codereview.chromium.org/10823177.
My changes: style nits, as well as fixing pnacl builds
original CL description follows:

This CL adds support for Debug and Release configs.
It moves functions that require knowledge of the Makefile to make_rules.py and
keeps functions that require understanding of the DSC files in
generate_make.py.

It adds a 'config' parameter to the embed in common.js.
Updates all index.html files to support the new config parameter.

make_rules.py has been converted to a class. This allows the object to persist
state about the build which allows us to remove knowledge of the make rules
from generate_make.py.

BUG=none
TBR=noelallen@chromium.org
NOTRY=true

Review URL: https://chromiumcodereview.appspot.com/10828187

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@150289 0039d316-1c4b-4281-b951-d872f2087c98
parent 1577f4ee
......@@ -460,6 +460,10 @@ def BuildStepCopyExamples(pepperdir, toolchains, build_experimental):
plat = getos.GetPlatform()
for arch in LIB_DICT[plat]:
buildbot_common.MakeDir(os.path.join(libdir, '%s_%s_host' % (plat, arch)))
for config in ['Debug', 'Release']:
buildbot_common.MakeDir(os.path.join(libdir, '%s_%s_host' % (plat, arch),
config))
srcdir = os.path.join(pepperdir, 'src')
buildbot_common.RemoveDir(srcdir)
......
......@@ -9,8 +9,7 @@ import optparse
import os
import sys
from make_rules import BuildDefineList, BuildLibList, BuildToolDict
from make_rules import BuildIncludeList, GetBuildRule, BUILD_RULES
from make_rules import MakeRules, SetVar, GenerateCleanRules, GenerateNMFRules
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
SDK_SRC_DIR = os.path.dirname(SCRIPT_DIR)
......@@ -24,7 +23,6 @@ PPAPI_DIR = os.path.join(SRC_DIR, 'ppapi')
sys.path.append(os.path.join(SDK_SRC_DIR, 'tools'))
import getos
SUPPORTED_HOSTS = ['win']
def ErrorExit(text):
ErrorMsgFunc(text)
......@@ -45,24 +43,6 @@ def WriteReplaced(srcpath, dstpath, replacements):
open(dstpath, 'wb').write(text)
def SetVar(varname, values):
if not values:
return varname + ':=\n'
line = varname + ':='
out = ''
for value in values:
if len(line) + len(value) > 78:
out += line[:-1] + '\n'
line = '%s+=%s ' % (varname, value)
else:
line += value + ' '
if line:
out += line[:-1] + '\n'
return out
def GenerateSourceCopyList(desc):
sources = []
# Add sources for each target
......@@ -89,6 +69,14 @@ def GetSourcesDict(sources):
return source_map
def GetProjectObjects(source_dict):
object_list = []
for key in ['.c', '.cc']:
for src in source_dict[key]:
object_list.append(os.path.splitext(src)[0])
return object_list
def GetPlatforms(plat_list, plat_filter):
platforms = []
for plat in plat_list:
......@@ -100,7 +88,7 @@ def GetPlatforms(plat_list, plat_filter):
def GenerateToolDefaults(desc, tools):
defaults = ''
for tool in tools:
defaults += BUILD_RULES[tool]['DEFS']
defaults += MakeRules(tool).BuildDefaults()
return defaults
......@@ -108,130 +96,85 @@ def GenerateSettings(desc, tools):
settings = SetVar('VALID_TOOLCHAINS', tools)
settings+= 'TOOLCHAIN?=%s\n\n' % tools[0]
for target in desc['TARGETS']:
name = target['NAME']
macro = name.upper()
project = target['NAME']
macro = project.upper()
srcs = GetSourcesDict(target['SOURCES'])
if srcs['.c']:
flags = target.get('CCFLAGS', ['$(NACL_CCFLAGS)'])
settings += SetVar(macro + '_CC', srcs['.c'])
settings += SetVar(macro + '_CCFLAGS', flags)
if srcs['.cc']:
flags = target.get('CXXFLAGS', ['$(NACL_CXXFLAGS)'])
settings += SetVar(macro + '_CXX', srcs['.cc'])
settings += SetVar(macro + '_CXXFLAGS', flags)
c_flags = target.get('CCFLAGS')
cc_flags = target.get('CXXFLAGS')
ld_flags = target.get('LDFLAGS')
flags = target.get('LDFLAGS', ['$(NACL_LDFLAGS)'])
settings += SetVar(macro + '_LDFLAGS', flags)
if c_flags:
settings += SetVar(macro + '_CCFLAGS', c_flags)
if cc_flags:
settings += SetVar(macro + '_CXXFLAGS', cc_flags)
if ld_flags:
settings += SetVar(macro + '_LDFLAGS', ld_flags)
return settings
def GetTarget(tool, targ_type, replace):
pattern = BUILD_RULES[tool]['TOOL'][targ_type]
return Replace(pattern, replace)
def GenerateCompile(target, tool, arch, srcs):
"""Generates a Compile target.
For the given target, toolset and architecture, returns a rule to generate
the object files for the set of sources.
Returns:
Returns a tuple containin the objects and the rule.
"""
rules = ''
name = target['NAME']
object_sets = []
defs = BuildDefineList(tool, target.get('DEFINES', []))
includes = BuildIncludeList(tool, target.get('INCLUDES', []))
if srcs['.c']:
replace = BuildToolDict(tool, name, arch, 'c',
DEFLIST=defs, INCLUDELIST=includes)
compile_rule = GetBuildRule(tool, 'CC')
rules += Replace(compile_rule, replace)
object_sets.append('$(%s)' % replace['<OBJS>'])
if srcs['.cc']:
replace = BuildToolDict(tool, name, arch, 'cc',
DEFLIST=defs, INCLUDELIST=includes)
compile_rule = GetBuildRule(tool, 'CXX')
rules += Replace(compile_rule, replace)
object_sets.append('$(%s)' % replace['<OBJS>'])
return (' '.join(object_sets), rules)
def GenerateLink(target, tool, arch, objs):
"""Generate a Link target.
Returns:
Returns a tuple containing the rule and target.
"""
targ_type = target['TYPE']
link_rule = GetBuildRule(tool, targ_type.upper())
libs = target.get('LIBS', [])
libs = BuildLibList(tool, libs)
replace = BuildToolDict(tool, target['NAME'], arch, 'nexe',
OBJS=objs, LIBLIST=libs)
rule = Replace(link_rule, replace)
target_out = GetTarget(tool, targ_type, replace)
return target_out, rule
def GenerateNMF(target, tool):
nmf_rule = BUILD_RULES[tool]['NMF']
replace = BuildToolDict(tool, target['NAME'])
rule = Replace(nmf_rule, replace)
target_out = GetTarget(tool, 'nmf', replace)
return target_out, rule
def GenerateRules(desc, tools):
all_targets = []
rules = ''
clean = []
for tc in tools:
rules += '\n#\n# Rules for %s toolchain\n#\n%s:\n\t$(MKDIR) %s\n' % (
tc, tc, tc)
rules = '#\n# Per target object lists\n#\n'
#Determine which projects are in the NMF files.
main = None
dlls = []
project_list = []
glibc_rename = []
for target in desc['TARGETS']:
name = target['NAME']
ptype = target['TYPE'].upper()
project = target['NAME']
project_list.append(project)
srcs = GetSourcesDict(target['SOURCES'])
for arch in BUILD_RULES[tc]['ARCHES']:
objs, comp_rule = GenerateCompile(target, tc, arch, srcs)
targs, link_rule = GenerateLink(target, tc, arch, objs)
rules += comp_rule + link_rule
clean.append(objs)
if target['TYPE'] == 'lib':
all_targets.append(targs)
if target['TYPE'] == 'main':
main = target
if ptype == 'MAIN':
main = project
if ptype == 'SO':
dlls.append(project)
for arch in ['x86_32', 'x86_64']:
glibc_rename.append('-n %s_%s.so,%s.so' % (project, arch, project))
objects = GetProjectObjects(srcs)
rules += SetVar('%s_OBJS' % project.upper(), objects)
if glibc_rename:
rules += SetVar('GLIBC_REMAP', glibc_rename)
configs = desc.get('CONFIGS', ['Debug', 'Release'])
for tc in tools:
makeobj = MakeRules(tc)
arches = makeobj.GetArches()
rules += makeobj.BuildDirectoryRules(configs)
for cfg in configs:
makeobj.SetConfig(cfg)
for target in desc['TARGETS']:
project = target['NAME']
ptype = target['TYPE']
srcs = GetSourcesDict(target['SOURCES'])
objs = GetProjectObjects(srcs)
defs = target.get('DEFINES', [])
incs = target.get('INCLUDES', [])
libs = target.get('LIBS', [])
lpaths = target.get('LIBPATHS', [])
ipaths = target.get('INCPATHS', [])
makeobj.SetProject(project, ptype, defs=defs, incs=incs, libs=libs)
for arch in arches:
makeobj.SetArch(arch)
for src in srcs.get('.c', []):
rules += makeobj.BuildCompileRule('CC', src)
for src in srcs.get('.cc', []):
rules += makeobj.BuildCompileRule('CXX', src)
rules += '\n'
rules += makeobj.BuildObjectList()
rules += makeobj.BuildLinkRule()
if main:
targs, nmf_rule = GenerateNMF(main, tc)
rules += nmf_rule
all_targets.append(targs)
rules += '\n.PHONY : clean\nclean:\n\t$(RM) $(DEPFILES) ' + ' '.join(clean)
rules += '\n\n-include $(DEPFILES)'
return ' '.join(all_targets), rules
rules += GenerateNMFRules(tc, main, dlls, cfg, arches)
rules += GenerateCleanRules(tools, configs)
rules += '\nall: $(ALL_TARGETS)\n'
return '', rules
def GenerateTargets(desc, tools):
targets = []
rules = ''
for tc in tools:
for target in desc['TARGETS']:
name = target['NAME']
replace = BuildToolDict(tc, name)
target = GetTarget(tc, target['TYPE'], replace)
if target:
targets.append(target)
return targets
def GenerateReplacements(desc, tools):
......@@ -246,8 +189,7 @@ def GenerateReplacements(desc, tools):
prerun = desc.get('PRE', '')
postlaunch = desc.get('POST', '')
targets = GenerateTargets(desc, tools)
target_def = 'all: ' + all_targets
target_def = 'all:'
return {
'__PROJECT_SETTINGS__' : settings,
......@@ -263,6 +205,7 @@ def GenerateReplacements(desc, tools):
# 'KEY' : ( <TYPE>, [Accepted Values], <Required?>)
DSC_FORMAT = {
'TOOLS' : (list, ['newlib', 'glibc', 'pnacl', 'win'], True),
'CONFIGS' : (list, ['Debug', 'Release'], False),
'PREREQ' : (list, '', False),
'TARGETS' : (list, {
'NAME': (str, '', True),
......@@ -417,13 +360,17 @@ def IsNexe(desc):
def ProcessHTML(srcroot, dstroot, desc, toolchains):
name = desc['NAME']
outdir = os.path.join(dstroot, desc['DEST'], name)
srcfile = os.path.join(srcroot, 'index.html')
tools = GetPlatforms(toolchains, desc['TOOLS'])
configs = ['Debug', 'Release']
for tool in tools:
dstfile = os.path.join(outdir, 'index_%s.html' % tool);
print 'Writting from %s to %s' % (srcfile, dstfile)
for cfg in configs:
dstfile = os.path.join(outdir, 'index_%s_%s.html' % (tool, cfg))
print 'Writing from %s to %s' % (srcfile, dstfile)
replace = {
'<config>': cfg,
'<NAME>': name,
'<TITLE>': desc['TITLE'],
'<tc>': tool
......@@ -431,6 +378,8 @@ def ProcessHTML(srcroot, dstroot, desc, toolchains):
WriteReplaced(srcfile, dstfile, replace)
replace['<tc>'] = tools[0]
replace['<config>'] = configs[0]
srcfile = os.path.join(SDK_SRC_DIR, 'build_tools', 'redirect.html')
dstfile = os.path.join(outdir, 'index.html')
WriteReplaced(srcfile, dstfile, replace)
......@@ -560,6 +509,7 @@ def main(argv):
print 'Using default toolchains: ' + ' '.join(toolchains)
master_projects = {}
for filename in args:
desc = LoadProject(filename, toolchains)
if not desc:
......
......@@ -8,9 +8,9 @@
<head>
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="-1" />
<meta http-equiv="Refresh" content="0;url=index_<tc>.html" />
<meta http-equiv="Refresh" content="0;url=index_<tc>_<config>.html" />
</head>
<body>
Redirecting to default example: <tc>
Redirecting to default example: <tc> <config>
</body>
</html>
......@@ -19,13 +19,13 @@ var common = (function () {
* @param {number} width The width to create the plugin.
* @param {number} height The height to create the plugin.
*/
function createNaClModule(name, tool, width, height) {
function createNaClModule(name, tool, config, width, height) {
var moduleEl = document.createElement('embed');
moduleEl.setAttribute('name', 'nacl_module');
moduleEl.setAttribute('id', 'nacl_module');
moduleEl.setAttribute('width', width);
moduleEl.setAttribute('height',height);
moduleEl.setAttribute('src', tool + '/' + name + '.nmf');
moduleEl.setAttribute('src', tool + '/' + config + '/' + name + '.nmf');
moduleEl.setAttribute('type', 'application/x-nacl');
// The <EMBED> element is wrapped inside a <DIV>, which has both a 'load'
......@@ -148,7 +148,7 @@ var common = (function () {
* @param {number} width The width to create the plugin.
* @param {number} height The height to create the plugin.
*/
function pageDidLoad(name, tool, width, height) {
function pageDidLoad(name, tool, config, width, height) {
// If the page loads before the Native Client module loads, then set the
// status message indicating that the module is still loading. Otherwise,
// do not change the status message.
......@@ -160,7 +160,7 @@ var common = (function () {
// plug-in graphic, if there is a problem.
width = typeof width !== 'undefined' ? width : 200;
height = typeof height !== 'undefined' ? height : 200;
createNaClModule(name, tool, width, height);
createNaClModule(name, tool, config, width, height);
attachDefaultListeners();
} else {
// It's possible that the Native Client module onload event fired
......
......@@ -137,7 +137,7 @@ Chrome executable.</li>
<embed name="nacl_module"
id="hello_world"
width=100 height=100
src="<tc>/debugging.nmf"
src="<tc>/<config>/debugging.nmf"
type="application/x-nacl" />
</div>
<hr>
......
......@@ -27,7 +27,7 @@ found in the LICENSE file.
}
</script>
</head>
<body onload="common.onload('<NAME>', '<tc>')">
<body onload="common.onload('<NAME>', '<tc>', '<config>')">
<h1><TITLE></h1>
<h2>Status: <code id="statusField">NO-STATUS</code></h2>
<div>Magic eightball: type a question below, press the button, and get a
......
......@@ -40,7 +40,7 @@
}
</script>
</head>
<body onload="common.onload('<NAME>', '<tc>', 256, 256)">
<body onload="common.onload('<NAME>', '<tc>', '<config>', 256, 256)">
<h1><TITLE></h1>
<h2>Status: <code id="statusField">NO-STATUS</code></h2>
<input type="file" id="FileInput" onchange="handleFileInput()" multiple>
......
......@@ -89,7 +89,7 @@
function(bytes) {
common.updateStatus(
'Allocated '+bytes+' bytes of persistant storage.');
common.createNaClModule('<NAME>', '<tc>', 200, 200);
common.createNaClModule('<NAME>', '<tc>', '<config>', 200, 200);
common.attachDefaultListeners();
},
function(e) { alert('Failed to allocate space') });
......
......@@ -27,7 +27,7 @@ found in the LICENSE file.
}
</script>
</head>
<body onload="common.onload('<NAME>', '<tc>', 480, 480)">
<body onload="common.onload('<NAME>', '<tc>', '<config>', 480, 480)">
<h1><TITLE></h1>
<h2>Status: <code id="statusField">NO-STATUS</code></h2>
<p>
......
......@@ -11,7 +11,7 @@ found in the LICENSE file.
<title><TITLE></title>
<script type="text/javascript" src="common.js"></script>
</head>
<body onload="common.onload('<NAME>', '<tc>', '800', '200')">
<body onload="common.onload('<NAME>', '<tc>', '<config>', '800', '200')">
<h1><TITLE></h1>
<h2>Status: <code id="statusField">NO-STATUS</code></h2>
<!-- The NaCl plugin will be embedded inside the element with id "listener".
......
......@@ -40,7 +40,7 @@ found in the LICENSE file.
}
</script>
</head>
<body onload="common.onload('<NAME>', '<tc>')">
<body onload="common.onload('<NAME>', '<tc>', '<config>')">
<h1><TITLE></h1>
<h2>Status: <code id="statusField">NO-STATUS</code></h2>
<table border=5 cellpadding=5% summary="A title and a result log">
......
......@@ -11,7 +11,7 @@ found in the LICENSE file.
<title><TITLE></title>
<script type="text/javascript" src="common.js"></script>
</head>
<body onload="common.onload('<NAME>', '<tc>')">
<body onload="common.onload('<NAME>', '<tc>', '<config>')">
<h1><TITLE></h1>
<h2>Status: <code id="statusField">NO-STATUS</code></h2>
<!-- The NaCl plugin will be embedded inside the element with id "listener".
......
......@@ -11,7 +11,7 @@ found in the LICENSE file.
<title><TITLE></title>
<script type="text/javascript" src="common.js"></script>
</head>
<body onload="common.onload('<NAME>', '<tc>', 640, 480)">
<body onload="common.onload('<NAME>', '<tc>', '<config>', 640, 480)">
<h1><TITLE></h1>
<h2>Status: <code id="statusField">NO-STATUS</code></h2>
<!-- The NaCl plugin will be embedded inside the element with id "listener".
......
......@@ -32,7 +32,7 @@
}
</script>
</head>
<body onload="common.onload('<NAME>', '<tc>')">
<body onload="common.onload('<NAME>', '<tc>', '<config>')">
<h1>Native Client Simple Module</h1>
<h2>Status: <code id="statusField">NO-STATUS</code></h2>
<!-- The NaCl plugin will be embedded inside the element with id "listener".
......
......@@ -31,7 +31,7 @@ found in the LICENSE file.
}
</script>
</head>
<body onload="common.onload('<NAME>', '<tc>')">
<body onload="common.onload('<NAME>', '<tc>', '<config>')">
<h1><TITLE></h1>
<h2>Status: <code id="statusField">NO-STATUS</code></h2>
......
......@@ -97,7 +97,7 @@ found in the LICENSE file.
}
</script>
</head>
<body onload="common.createNaClModule('<NAME>', '<tc>', 200, 200)">
<body onload="common.createNaClModule('<NAME>', '<tc>', '<config>',200, 200)">
<h1><TITLE></h1>
<h2>Status: <code id="statusField">NO-STATUS</code></h2>
<h2>Event Log</h2>
......
......@@ -11,7 +11,7 @@ found in the LICENSE file.
<title><TITLE></title>
<script type="text/javascript" src="common.js"></script>
</head>
<body onload="common.onload('<NAME>', '<tc>', 300, 300)">
<body onload="common.onload('<NAME>', '<tc>', '<config>', 300, 300)">
<h1><TITLE></h1>
<h2>Status: <code id="statusField">NO-STATUS</code></h2>
<h1>Full-screen and Mouse-lock Example</h1>
......
......@@ -40,7 +40,7 @@ found in the LICENSE file.
}
</script>
</head>
<body onload="common.onload('<NAME>', '<tc>')">
<body onload="common.onload('<NAME>', '<tc>', '<config>')">
<h1><TITLE></h1>
<h2>Status: <code id="statusField">NO-STATUS</code></h2>
<button onclick="cancelQueue()">Kill worker thread and queue</button>
......
......@@ -30,7 +30,7 @@ found in the LICENSE file.
}
</script>
</head>
<body onload="common.onload('<NAME>', '<tc>')" onunload="pageDidUnload()">
<body onload="common.onload('<NAME>', '<tc>', '<config>')" onunload="pageDidUnload()">
<h1><TITLE></h1>
<h2>Status: <code id="statusField">NO-STATUS</code></h2>
<p>
......
......@@ -46,7 +46,7 @@ found in the LICENSE file.
function(bytes) {
common.updateStatus(
'Allocated '+bytes+' bytes of persistent storage.');
common.createNaClModule('<NAME>', '<tc>', 800, 600);
common.createNaClModule('<NAME>', '<tc>', '<config>', 800, 600);
common.attachDefaultListeners();
},
function(e) { alert('Failed to allocate space'); });
......
......@@ -36,7 +36,7 @@ found in the LICENSE file.
}
</script>
</head>
<body onload="common.onload('<NAME>', '<tc>')">
<body onload="common.onload('<NAME>', '<tc>', '<config>')">
<h1><TITLE></h1>
<h2>Status: <code id="statusField">NO-STATUS</code></h2>
......
......@@ -26,7 +26,7 @@ found in the LICENSE file.
}
</script>
</head>
<body onload="common.onload('<NAME>', '<tc>', 480, 480)">
<body onload="common.onload('<NAME>', '<tc>', '<config>', 480, 480)">
<h1><TITLE></h1>
<h2>Status: <code id="statusField">NO-STATUS</code></h2>
<p>
......
......@@ -36,7 +36,7 @@ found in the LICENSE file.
}
</script>
</head>
<body onload="common.onload('<NAME>', '<tc>')">
<body onload="common.onload('<NAME>', '<tc>', '<config>')">
<h1><TITLE></h1>
<h2>Status: <code id="statusField">NO-STATUS</code></h2>
<div>Set a server URL, then push "Connect" button to establish a connection.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment