Updated logging to allow it to be printed to the console as well as
file. Updated build_chromeos.py to use logging properly.
PRESUBMIT=passed
R=asharif,bjanakiraman
DELTA=232 (183 added, 35 deleted, 14 changed)
OCL=44971-p2
RCL=45003-p2
RDATE=2010/11/03 17:32:32
P4 change: 42605541
diff --git a/v14/build_chromeos.py b/v14/build_chromeos.py
new file mode 100755
index 0000000..747376b
--- /dev/null
+++ b/v14/build_chromeos.py
@@ -0,0 +1,136 @@
+#!/usr/bin/python2.6
+#
+# Copyright 2010 Google Inc. All Rights Reserved.
+
+"""Script to checkout the ChromeOS source.
+
+This script sets up the ChromeOS source in the given directory, matching a
+particular release of ChromeOS.
+"""
+
+__author__ = "raymes@google.com (Raymes Khoury)"
+
+import optparse
+import os
+import sys
+from utils import utils
+
+
+def Usage(parser, message):
+ print "ERROR: " + message
+ parser.print_help()
+ sys.exit(0)
+
+
+def ExecuteCommandInChroot(chromeos_root, toolchain_root, command,
+ return_output=False):
+ commands = []
+ tc_enter_chroot = (os.path.dirname(os.path.abspath(__file__)) +
+ "/tc-enter-chroot.sh")
+ commands.append("%s --chromeos_root=%s --toolchain_root=%s -- %s"
+ % (tc_enter_chroot, chromeos_root, toolchain_root, command))
+ return utils.RunCommands(commands, return_output)
+
+
+def StoreFile(filename, contents):
+ utils.RunCommand("echo '%s' > %s" % (contents, filename))
+
+
+def Main():
+ """Build ChromeOS."""
+ # Common initializations
+ (rootdir, basename) = utils.GetRoot(sys.argv[0])
+ utils.InitLogger(rootdir, basename)
+
+ parser = optparse.OptionParser()
+ parser.add_option("--chromeos_root", dest="chromeos_root",
+ help="Target directory for ChromeOS installation.")
+ parser.add_option("--toolchain_root", dest="toolchain_root",
+ help="The gcctools directory of your P4 checkout.")
+ parser.add_option("--clobber_chroot", dest="clobber_chroot",
+ action="store_true", help=
+ "Delete the chroot and start fresh", default=False)
+ parser.add_option("--clobber_board", dest="clobber_board",
+ action="store_true",
+ help="Delete the board and start fresh", default=False)
+ parser.add_option("--cflags", dest="cflags",
+ help="CFLAGS for the ChromeOS packages")
+ parser.add_option("--cxxflags", dest="cxxflags",
+ help="CXXFLAGS for the ChromeOS packages")
+ parser.add_option("--ldflags", dest="ldflags",
+ help="LDFLAGS for the ChromeOS packages")
+ parser.add_option("--board", dest="board",
+ help="ChromeOS target board, e.g. x86-generic")
+
+ options = parser.parse_args()[0]
+
+ if options.chromeos_root is None:
+ Usage(parser, "--chromeos_root must be set")
+
+ if options.toolchain_root is None:
+ Usage(parser, "--toolchain_root must be set")
+
+ if options.board is None:
+ Usage(parser, "--board must be set")
+
+ # Make chroot
+ commands = []
+ commands.append("cd " + options.chromeos_root + "/src/scripts")
+ clobber_chroot = ""
+ if options.clobber_chroot:
+ clobber_chroot = "--replace"
+ commands.append("./make_chroot --fast " + clobber_chroot)
+ utils.RunCommands(commands)
+
+ # Setup board
+ force = ""
+ if options.clobber_board:
+ force = "--force"
+ ExecuteCommandInChroot(options.chromeos_root, options.toolchain_root,
+ "FEATURES=\\\"keepwork noclean\\\" "
+ "./setup_board --nousepkg --board=%s "
+ "%s"
+ % (options.board, force))
+
+ # Find Chrome browser version
+ chrome_version = (ExecuteCommandInChroot
+ (options.chromeos_root, options.toolchain_root,
+ "./chromeos_version.sh | "
+ "grep CHROME_BUILD", True))
+
+ chrome_version = chrome_version[1].strip().split("=")
+ if len(chrome_version) == 2:
+ chrome_version = chrome_version[1]
+ else:
+ chrome_version = ""
+
+ # Modify make.conf to add CFLAGS/CXXFLAGS/LDFLAGS
+ ExecuteCommandInChroot(options.chromeos_root, options.toolchain_root,
+ "mv /build/%s/etc/make.conf "
+ "/build/%s/etc/make.conf.orig"
+ % (options.board, options.board))
+ makeconf = ("source /build/%s/etc/make.conf.orig\n"
+ "/CFLAGS=%s\nCXXFLAGS=%s\nLDFLAGS=%s\n" %
+ (options.board, options.cflags,
+ options.cxxflags, options.ldflags))
+ StoreFile("%s/chroot/build/%s/etc/make.conf" %
+ (options.chromeos_root, options.board), makeconf)
+
+ # Build packages
+ ExecuteCommandInChroot(options.chromeos_root, options.toolchain_root,
+ "CHROME_ORIGIN=SERVER_SOURCE CHROME_BUILD=%s "
+ "./build_packages --withdev "
+ "--board=%s --withtest --withautotest"
+ % (chrome_version, options.board))
+
+ # Build image
+ ExecuteCommandInChroot(options.chromeos_root, options.toolchain_root,
+ "./build_image --board=%s")
+
+ # Mod image for test
+ ExecuteCommandInChroot(options.chromeos_root, options.toolchain_root,
+ "./mod_image_for_test --board=%s")
+
+
+if __name__ == "__main__":
+ Main()
diff --git a/v14/setup_chromeos.py b/v14/setup_chromeos.py
index 4e5c3c6..b3360cf 100755
--- a/v14/setup_chromeos.py
+++ b/v14/setup_chromeos.py
@@ -31,7 +31,7 @@
def GetTags():
- res = utils.DoCommand(GIT_TAGS_CMD)
+ res = utils.RunCommand(GIT_TAGS_CMD, True)
return res[1].strip().split("\n")
diff --git a/v14/utils/utils.py b/v14/utils/utils.py
index 5b6a64e..34aebb4 100755
--- a/v14/utils/utils.py
+++ b/v14/utils/utils.py
@@ -8,34 +8,76 @@
__author__ = "asharif@google.com (Ahmad Sharif)"
import os
+import select
import subprocess
+import sys
class Logger(object):
"""Logging helper class."""
- def __init__ (self, rootdir, basefilename):
+ def __init__ (self, rootdir, basefilename, print_console=True):
self._logdir = rootdir + "/logs/"
AtomicMkdir(self._logdir)
self._basefilename = basefilename
- self._cmdfd = open(self._logdir + self._basefilename + ".cmd", "w", 0755)
- self._stout = open(self._logdir + self._basefilename + ".out", "w")
- self._sterr = open(self._logdir + self._basefilename + ".err", "w")
-
- def Stdout(self):
- return self._stout
-
- def Stderr(self):
- return self._sterr
+ self.cmdfd = open(self._logdir + self._basefilename + ".cmd", "w", 0755)
+ self.stdout = open(self._logdir + self._basefilename + ".out", "w")
+ self.stderr = open(self._logdir + self._basefilename + ".err", "w")
+ self.print_console = print_console
def Logcmd(self, cmd):
- self._cmdfd.write(str(cmd) + "\n")
+ self.cmdfd.write(str(cmd) + "\n")
+ if self.print_console:
+ print "CMD: " + str(cmd)
+
+ def RunLoggedCommand(self, cmd, return_output=False):
+ """Run a command and log the output."""
+ cmdlist = ["bash", "-c", cmd]
+ self.Logcmd(cmdlist)
+
+ p = subprocess.Popen(cmdlist, stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+
+ full_stdout = ""
+ full_stderr = ""
+
+ # Pull output from pipes, send it to file/stdout/string
+ out = err = None
+ while True:
+ fds = select.select([p.stdout, p.stderr], [], [], 0.1)[0]
+ for fd in fds:
+ if fd == p.stdout:
+ out = os.read(p.stdout.fileno(), 4096)
+ if return_output:
+ full_stdout += out
+ if self.print_console:
+ sys.stdout.write(out)
+ sys.stdout.flush()
+ self.stdout.write(out)
+ self.stdout.flush()
+ if fd == p.stderr:
+ err = os.read(p.stderr.fileno(), 4096)
+ if return_output:
+ full_stderr += err
+ if self.print_console:
+ sys.stderr.write(err)
+ sys.stderr.flush()
+ self.stderr.write(err)
+ self.stderr.flush()
+
+ if out == err == "":
+ break
+
+ p.wait()
+ if return_output:
+ return (p.returncode, full_stdout, full_stderr)
+ return p.returncode
def __del__ (self):
- self._cmdfd.close()
- self._stout.close()
- self._sterr.close()
+ self.cmdfd.close()
+ self.stdout.close()
+ self.stderr.close()
return
@@ -54,44 +96,14 @@
return (os.path.dirname(abs_path), os.path.basename(abs_path))
-def RunCommand(cmd):
+def RunCommand(cmd, return_output=False):
""""Run a command while redirecting stdout and stderr to predefined files."""
- cmdlist = ["bash", "-c", cmd]
- main_logger.Logcmd(cmdlist)
- stout = main_logger.Stdout()
- sterr = main_logger.Stderr()
- p = subprocess.Popen(cmdlist, stdout=stout, stderr=sterr)
- p.wait()
- return p.returncode
+ return main_logger.RunLoggedCommand(cmd, return_output)
-def RunCommands(cmdlist):
+def RunCommands(cmdlist, return_output=False):
cmd = " ; " .join(cmdlist)
- print "CMD=", cmd
- return RunCommand(cmd)
-
-
-def DoCommand(cmd):
- """"Run a command and return stdout and stderr as string. Log output."""
- cmdlist = ["bash", "-c", cmd]
- main_logger.Logcmd(cmdlist)
- p = subprocess.Popen(cmdlist, stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
- (out, err) = p.communicate()
- # For now, log the output and error in the standard place. May need to revisit
- # if its making out files too large.
- stout = main_logger.Stdout()
- sterr = main_logger.Stderr()
- stout.write(out)
- sterr.write(err)
- stout.flush()
- sterr.flush()
- return (p.returncode, out, err)
-
-
-def DoCommands(cmdlist):
- cmd = " ; " .join(cmdlist)
- return DoCommand(cmd)
+ return RunCommand(cmd, return_output)
def AtomicMkdir(newdir):