blob: 992fb639e3157bf04551b8e2f981f98bc9fa5571 [file] [log] [blame]
#!/usr/bin/python2.4
#
# Copyright 2009 Google Inc. All Rights Reserved.
"""Run Android benchmarks
Compiles the specified targets and gets info on running them
"""
__author__ = 'ushakov@google.com (Maxim Ushakov)'
import os
import sys
import getopt
import subprocess
options = [
["action=", ["build","build-fdo","clean","export","runcmd","getsize"]],
["mode=", ["arm","thumb"]],
["toolchain=", [], "toolchain path"],
["add_cflags=", [], "additional flags for compilation"],
["add_ldflags=", [], "additional flags for linking"],
["disable_cflags=", [], "default cflags to remove"],
["android_branch=", ["eclair","mainline","cupcake"]],
["build_target=", ["lib","bench"]],
["mute=", ["on","off"]],
["asm=", ["on","off"]],
["makeopts=", [], "override make options (default -j4 --warn-undefined_variables)"],
["serial=", [], "\"emulator\" or device serial number"],
["help", []],
]
def ShowUsage():
"""Print out the usage info.
"""
print "Options:"
for x in options:
opt = x[0]
if opt[-1:] == '=':
opt = opt[:-1]
s = " [ --%s" % x[0]
if len(x[1]) != 0:
s += "%s" % "|".join(x[1])
if len(x) > 2:
s += " (%s)" % x[2]
print s, "]"
set_opts = {}
def ParseOptions(argv):
"""Parse the command-line options and check validity."
"""
try:
opts, args = getopt.gnu_getopt(argv, "", [x[0] for x in options])
except getopt.GetoptError, err:
print "Error:", str(err)
ShowUsage()
return False
if len(args) != 0:
ShowUsage()
return False
for p in opts:
opt = p[0][2:]
set_opts[opt] = p[1]
if "help" in set_opts:
ShowUsage()
return False
ok = True
for x in options:
opt = x[0]
if opt[-1:] == '=':
opt = opt[:-1]
if opt not in set_opts:
continue
if len(x[1]) == 0:
continue
if set_opts[opt] not in x[1]:
print "Error: option --%s takes args in [%s]" % (opt, ", ".join(x[1]))
ok = False
if "action" not in set_opts:
print "No --action specified -- no work done"
return False
return ok
def RunCmd(cmdline, silent=False):
if not silent:
print cmdline
ret = subprocess.call(cmdline, shell=True)
if ret == 0:
return ret
if ret < 0:
print "Command %s killbed by signal %s" % (cmdline, -ret)
else:
print "Command %s exited with status %s" % (cmdline, ret)
return ret
def CreateDummyBench():
"""Create dummy *_bench file if benchmark does not generate executable.
This function is mainly for perflab integration. Since perflab requires
that each benchmark must have a $(bench_name)_bench executable, we need
to create a dummy one (0 size) if the benchmark does not generate this
executable automatically (eg. gcstone).
"""
# Get the current benchmark name.
cur_path = os.getcwd()
bench_name = os.path.basename(cur_path)
# Create one if $(out)/$(bench_name)_bench does not exist.
bench_exe = os.path.join(cur_path, "out", "%s_bench" % bench_name)
if not os.path.exists(bench_exe):
if not os.path.exists(os.path.join(cur_path, 'out')):
print "Error: output path does not exist. Build must be wrong."
return False
dummy_file = open(bench_exe, "w")
dummy_file.close()
os.chmod(bench_exe, 0750)
return True
def FindTopPath():
"""Find top directory of the benchmark suite."""
cur_path = os.getcwd()
if os.path.exists(os.path.join(cur_path, "../scripts/build/main.mk")):
return ".."
elif os.path.exists(os.path.join(cur_path, "../../scripts/build/main.mk")):
return "../.."
else:
return ""
_MAKE_CMD_TEMPLATE = "make %(opts)s -f %(mainmk)s %(vars)s %(target)s"
def main(argv):
if not ParseOptions(argv[1:]):
return 1
top_path = FindTopPath()
if not top_path:
print "Error: This script must be called from benchmark dir!"
return 1
os.putenv("RVCT40INC","")
os.putenv("RVCT40LIB","")
make_vars = ""
if "mode" in set_opts:
make_vars += " COMPILE_MODE=%s" % set_opts["mode"]
if "toolchain" in set_opts:
make_vars += " TOOLCHAIN=%s" % set_opts["toolchain"]
if "add_cflags" in set_opts:
make_vars += " ADD_CFLAGS=\"%s\"" % set_opts["add_cflags"]
if "add_ldflags" in set_opts:
make_vars += " ADD_LDFLAGS=\"%s\"" % set_opts["add_ldflags"]
if "disable_cflags" in set_opts:
make_vars += " DISABLE_CFLAGS=\"%s\"" % set_opts["disable_cflags"]
if "android_branch" in set_opts:
make_vars += " ANDROID_BRANCH=%s" % set_opts["android_branch"]
if "build_target" in set_opts:
make_vars += " BUILD_TARGET=%s" % set_opts["build_target"]
if "mute" in set_opts:
make_vars += " MUTE=%s" % set_opts["mute"]
if "asm" in set_opts:
make_vars += " ASM=%s" % set_opts["asm"]
if "makeopts" in set_opts:
make_opts = set_opts["makeopts"]
else:
make_opts = "-j4 --warn-undefined-variables"
make_dict = {
"opts" : make_opts,
"mainmk" : "%s/scripts/build/main.mk" % top_path,
"vars" : make_vars,
"target": set_opts["action"]
}
if set_opts["action"] == "build-fdo":
# First, do a clean
my_dict = make_dict.copy()
my_dict["target"] = "clean"
cmd = _MAKE_CMD_TEMPLATE % (my_dict)
ret = RunCmd(cmd)
if ret != 0: return ret
# Compile with profiler support.
my_dict = make_dict.copy()
my_dict["vars"] = (make_dict["vars"] + " SKIP_PRELINKING=1" +
" FDO_BUILD=1 ADD_CFLAGS=\"%s\" ADD_LDFLAGS=\"%s\"" % \
(set_opts.get("add_cflags","") +
" -ftest-coverage -fprofile-generate=/data/local/profile/"
" -DANDROID_FDO",
set_opts.get("add_ldflags","") +
" -fprofile-generate=/data/local/profile/"
" -Wl,--stub-group-size=2000000"))
my_dict["target"] = "build"
cmd = _MAKE_CMD_TEMPLATE % (my_dict)
ret = RunCmd(cmd)
if ret != 0: return ret
run_fdo_device = ""
if "serial" in set_opts:
if set_opts["serial"] == "emulator":
run_fdo_device = "--emulator"
else:
run_fdo_device = "--s %s" % set_opts["serial"]
ret = RunCmd("%s/scripts/run_on_android.py %s --fdo-run"
% (top_path, run_fdo_device))
if ret != 0: return ret
# keep the original *.gcno files.
ret = RunCmd("mv obj obj2")
if ret != 0: return ret
# now we have FDO output in ./fdo/ -- clean up and move it to obj dir
my_dict = make_dict.copy()
my_dict["target"] = "clean"
cmd = _MAKE_CMD_TEMPLATE % (my_dict)
ret = RunCmd(cmd)
if ret != 0: return ret
ret = RunCmd("mv fdo obj")
if ret != 0: return ret
# Compile for the second time, now using profiles.
my_dict = make_dict.copy()
my_dict["vars"] = (make_dict["vars"] +
" FDO_BUILD=1 ADD_CFLAGS=\"%s\" ADD_LDFLAGS=\"%s\"" % \
(set_opts.get("add_cflags","") + " -fprofile-use"
" -DANDROID_FDO",
set_opts.get("add_ldflags","") + " -fprofile-use"))
my_dict["target"] = "build"
cmd = _MAKE_CMD_TEMPLATE % (my_dict)
ret = RunCmd(cmd)
if ret != 0: return ret
CreateDummyBench()
return ret
else:
cmd = _MAKE_CMD_TEMPLATE % (make_dict)
# For runcmd, export and getsize, we do not want to print the command.
silent = set_opts["action"] in ("runcmd", "export", "getsize")
ret = RunCmd(cmd, silent)
if ret != 0: return ret
if set_opts["action"] == "build":
CreateDummyBench()
if __name__ == '__main__':
sys.exit(main(sys.argv))