|  | #!/usr/bin/env python | 
|  |  | 
|  | """ | 
|  | This script determines the given package's openbmc dependencies from its | 
|  | configure.ac file where it downloads, configures, builds, and installs each of | 
|  | these dependencies. Then the given package is configured, built, and installed | 
|  | prior to executing its unit tests. | 
|  | """ | 
|  |  | 
|  | from urlparse import urljoin | 
|  | from subprocess import check_call, call | 
|  | import os | 
|  | import sys | 
|  | import argparse | 
|  |  | 
|  |  | 
|  | def check_call_cmd(dir, *cmd): | 
|  | """ | 
|  | Verbose prints the directory location the given command is called from and | 
|  | the command, then executes the command using check_call. | 
|  |  | 
|  | Parameter descriptions: | 
|  | dir                 Directory location command is to be called from | 
|  | cmd                 List of parameters constructing the complete command | 
|  | """ | 
|  | printline(dir, ">", " ".join(cmd)) | 
|  | check_call(cmd) | 
|  |  | 
|  |  | 
|  | def clone_pkg(pkg): | 
|  | """ | 
|  | Clone the given openbmc package's git repository from gerrit into | 
|  | the WORKSPACE location | 
|  |  | 
|  | Parameter descriptions: | 
|  | pkg                 Name of the package to clone | 
|  | """ | 
|  | pkg_repo = urljoin('https://gerrit.openbmc-project.xyz/openbmc/', pkg) | 
|  | os.chdir(WORKSPACE) | 
|  | check_call_cmd(WORKSPACE, 'git', 'clone', pkg_repo) | 
|  |  | 
|  |  | 
|  | def get_deps(configure_ac): | 
|  | """ | 
|  | Parse the given 'configure.ac' file for package dependencies and return | 
|  | a list of the dependencies found. | 
|  |  | 
|  | Parameter descriptions: | 
|  | configure_ac        Opened 'configure.ac' file object | 
|  | """ | 
|  | line = "" | 
|  | dep_pkgs = [] | 
|  | for cfg_line in configure_ac: | 
|  | # Remove whitespace & newline | 
|  | cfg_line = cfg_line.rstrip() | 
|  | # Check for line breaks | 
|  | if cfg_line.endswith('\\'): | 
|  | line += str(cfg_line[:-1]) | 
|  | continue | 
|  | line = line+cfg_line | 
|  |  | 
|  | # Find any defined dependency | 
|  | for macro_key in DEPENDENCIES: | 
|  | if not line.startswith(macro_key): | 
|  | continue | 
|  | for dep_key in DEPENDENCIES[macro_key]: | 
|  | if line.find(dep_key) == -1: | 
|  | continue | 
|  | dep_pkgs += [DEPENDENCIES[macro_key][dep_key]] | 
|  | line = "" | 
|  |  | 
|  | return dep_pkgs | 
|  |  | 
|  |  | 
|  | def build_depends(pkg, pkgdir, dep_installed): | 
|  | """ | 
|  | For each package(pkg), starting with the package to be unit tested, | 
|  | parse its 'configure.ac' file from within the package's directory(pkgdir) | 
|  | for each package dependency defined recursively doing the same thing | 
|  | on each package found as a dependency. | 
|  |  | 
|  | Parameter descriptions: | 
|  | pkg                 Name of the package | 
|  | pkgdir              Directory where package source is located | 
|  | dep_installed       Current list of dependencies and installation status | 
|  | """ | 
|  | os.chdir(pkgdir) | 
|  | # Open package's configure.ac | 
|  | with open("configure.ac", "rt") as configure_ac: | 
|  | # Retrieve dependency list from package's configure.ac | 
|  | configure_ac_deps = get_deps(configure_ac) | 
|  | for dep_pkg in configure_ac_deps: | 
|  | # Dependency package not already known | 
|  | if dep_installed.get(dep_pkg) is None: | 
|  | # Dependency package not installed | 
|  | dep_installed[dep_pkg] = False | 
|  | clone_pkg(dep_pkg) | 
|  | # Determine this dependency package's | 
|  | # dependencies and install them before | 
|  | # returning to install this package | 
|  | dep_pkgdir = os.path.join(WORKSPACE, dep_pkg) | 
|  | dep_installed = build_depends(dep_pkg, dep_pkgdir, | 
|  | dep_installed) | 
|  | else: | 
|  | # Dependency package known and installed | 
|  | if dep_installed[dep_pkg]: | 
|  | continue | 
|  | else: | 
|  | # Cyclic dependency failure | 
|  | raise Exception("Cyclic dependencies found in "+pkg) | 
|  |  | 
|  | # Build & install this package | 
|  | if not dep_installed[pkg]: | 
|  | conf_flags = "" | 
|  | os.chdir(pkgdir) | 
|  | # Add any necessary configure flags for package | 
|  | if CONFIGURE_FLAGS.get(pkg) is not None: | 
|  | conf_flags = " ".join(CONFIGURE_FLAGS.get(pkg)) | 
|  | check_call_cmd(pkgdir, './bootstrap.sh') | 
|  | check_call_cmd(pkgdir, './configure', conf_flags) | 
|  | check_call_cmd(pkgdir, 'make') | 
|  | check_call_cmd(pkgdir, 'make', 'install') | 
|  | dep_installed[pkg] = True | 
|  |  | 
|  | return dep_installed | 
|  |  | 
|  |  | 
|  | if __name__ == '__main__': | 
|  | # CONFIGURE_FLAGS = [GIT REPO]:[CONFIGURE FLAGS] | 
|  | CONFIGURE_FLAGS = { | 
|  | 'phosphor-objmgr': ['--enable-unpatched-systemd'] | 
|  | } | 
|  |  | 
|  | # DEPENDENCIES = [MACRO]:[library/header]:[GIT REPO] | 
|  | DEPENDENCIES = { | 
|  | 'AC_CHECK_LIB': {'mapper': 'phosphor-objmgr'}, | 
|  | 'AC_CHECK_HEADER': {'host-ipmid/ipmid-api.h': 'phosphor-host-ipmid'} | 
|  | } | 
|  |  | 
|  | # Set command line arguments | 
|  | parser = argparse.ArgumentParser() | 
|  | parser.add_argument("-w", "--workspace", dest="WORKSPACE", required=True, | 
|  | help="Workspace directory location(i.e. /home)") | 
|  | parser.add_argument("-p", "--package", dest="PACKAGE", required=True, | 
|  | help="OpenBMC package to be unit tested") | 
|  | parser.add_argument("-v", "--verbose", action="store_true", | 
|  | help="Print additional package status messages") | 
|  | args = parser.parse_args(sys.argv[1:]) | 
|  | WORKSPACE = args.WORKSPACE | 
|  | UNIT_TEST_PKG = args.PACKAGE | 
|  | if args.verbose: | 
|  | def printline(*line): | 
|  | for arg in line: | 
|  | print arg, | 
|  | print | 
|  | else: | 
|  | printline = lambda *l: None | 
|  |  | 
|  | prev_umask = os.umask(000) | 
|  | # Determine dependencies and install them | 
|  | dep_installed = dict() | 
|  | dep_installed[UNIT_TEST_PKG] = False | 
|  | dep_installed = build_depends(UNIT_TEST_PKG, | 
|  | os.path.join(WORKSPACE, UNIT_TEST_PKG), | 
|  | dep_installed) | 
|  | os.chdir(os.path.join(WORKSPACE, UNIT_TEST_PKG)) | 
|  | # Run package unit tests | 
|  | check_call_cmd(os.path.join(WORKSPACE, UNIT_TEST_PKG), 'make', 'check') | 
|  | os.umask(prev_umask) |