blob: f86e37d4904c521657cf32973b97905c415d6c3d [file] [log] [blame]
Matthew Barthccb7f852016-11-23 17:43:02 -06001#!/usr/bin/env python
2
3"""
4This script determines the given package's openbmc dependencies from its
5configure.ac file where it downloads, configures, builds, and installs each of
6these dependencies. Then the given package is configured, built, and installed
7prior to executing its unit tests.
8"""
9
Matthew Barthd1810372016-12-19 16:57:21 -060010from git import Repo
Matthew Barthccb7f852016-11-23 17:43:02 -060011from urlparse import urljoin
Matthew Barth33df8792016-12-19 14:30:17 -060012from subprocess import check_call, call
Matthew Barthccb7f852016-11-23 17:43:02 -060013import os
14import sys
Matthew Barth33df8792016-12-19 14:30:17 -060015import argparse
16
17
18def check_call_cmd(dir, *cmd):
19 """
20 Verbose prints the directory location the given command is called from and
21 the command, then executes the command using check_call.
22
23 Parameter descriptions:
24 dir Directory location command is to be called from
25 cmd List of parameters constructing the complete command
26 """
27 printline(dir, ">", " ".join(cmd))
28 check_call(cmd)
Matthew Barthccb7f852016-11-23 17:43:02 -060029
30
31def clone_pkg(pkg):
Matthew Barth33df8792016-12-19 14:30:17 -060032 """
33 Clone the given openbmc package's git repository from gerrit into
34 the WORKSPACE location
35
36 Parameter descriptions:
37 pkg Name of the package to clone
38 """
Matthew Barthccb7f852016-11-23 17:43:02 -060039 pkg_repo = urljoin('https://gerrit.openbmc-project.xyz/openbmc/', pkg)
Matthew Barthd1810372016-12-19 16:57:21 -060040 os.mkdir(os.path.join(WORKSPACE, pkg))
41 printline(os.path.join(WORKSPACE, pkg), "> git clone", pkg_repo, "./")
42 return Repo.clone_from(pkg_repo, os.path.join(WORKSPACE, pkg))
Matthew Barth33df8792016-12-19 14:30:17 -060043
44
45def get_deps(configure_ac):
46 """
47 Parse the given 'configure.ac' file for package dependencies and return
48 a list of the dependencies found.
49
50 Parameter descriptions:
51 configure_ac Opened 'configure.ac' file object
52 """
53 line = ""
54 dep_pkgs = []
55 for cfg_line in configure_ac:
56 # Remove whitespace & newline
57 cfg_line = cfg_line.rstrip()
58 # Check for line breaks
59 if cfg_line.endswith('\\'):
60 line += str(cfg_line[:-1])
61 continue
62 line = line+cfg_line
63
64 # Find any defined dependency
65 for macro_key in DEPENDENCIES:
66 if not line.startswith(macro_key):
67 continue
68 for dep_key in DEPENDENCIES[macro_key]:
69 if line.find(dep_key) == -1:
70 continue
71 dep_pkgs += [DEPENDENCIES[macro_key][dep_key]]
72 line = ""
73
74 return dep_pkgs
Matthew Barthccb7f852016-11-23 17:43:02 -060075
76
77def build_depends(pkg, pkgdir, dep_installed):
78 """
79 For each package(pkg), starting with the package to be unit tested,
80 parse its 'configure.ac' file from within the package's directory(pkgdir)
81 for each package dependency defined recursively doing the same thing
82 on each package found as a dependency.
83
84 Parameter descriptions:
85 pkg Name of the package
86 pkgdir Directory where package source is located
87 dep_installed Current list of dependencies and installation status
88 """
89 os.chdir(pkgdir)
90 # Open package's configure.ac
Matthew Barth33df8792016-12-19 14:30:17 -060091 with open("configure.ac", "rt") as configure_ac:
92 # Retrieve dependency list from package's configure.ac
93 configure_ac_deps = get_deps(configure_ac)
94 for dep_pkg in configure_ac_deps:
95 # Dependency package not already known
96 if dep_installed.get(dep_pkg) is None:
97 # Dependency package not installed
98 dep_installed[dep_pkg] = False
Matthew Barthd1810372016-12-19 16:57:21 -060099 dep_repo = clone_pkg(dep_pkg)
Matthew Barth33df8792016-12-19 14:30:17 -0600100 # Determine this dependency package's
101 # dependencies and install them before
102 # returning to install this package
103 dep_pkgdir = os.path.join(WORKSPACE, dep_pkg)
Matthew Barthd1810372016-12-19 16:57:21 -0600104 dep_installed = build_depends(dep_pkg,
105 dep_repo.working_dir,
Matthew Barth33df8792016-12-19 14:30:17 -0600106 dep_installed)
107 else:
108 # Dependency package known and installed
109 if dep_installed[dep_pkg]:
Matthew Barthccb7f852016-11-23 17:43:02 -0600110 continue
Matthew Barth33df8792016-12-19 14:30:17 -0600111 else:
112 # Cyclic dependency failure
113 raise Exception("Cyclic dependencies found in "+pkg)
Matthew Barthccb7f852016-11-23 17:43:02 -0600114
115 # Build & install this package
116 if not dep_installed[pkg]:
117 conf_flags = ""
118 os.chdir(pkgdir)
119 # Add any necessary configure flags for package
120 if CONFIGURE_FLAGS.get(pkg) is not None:
121 conf_flags = " ".join(CONFIGURE_FLAGS.get(pkg))
Matthew Barth33df8792016-12-19 14:30:17 -0600122 check_call_cmd(pkgdir, './bootstrap.sh')
123 check_call_cmd(pkgdir, './configure', conf_flags)
124 check_call_cmd(pkgdir, 'make')
125 check_call_cmd(pkgdir, 'make', 'install')
Matthew Barthccb7f852016-11-23 17:43:02 -0600126 dep_installed[pkg] = True
127
128 return dep_installed
129
130
131if __name__ == '__main__':
132 # CONFIGURE_FLAGS = [GIT REPO]:[CONFIGURE FLAGS]
133 CONFIGURE_FLAGS = {
134 'phosphor-objmgr': ['--enable-unpatched-systemd']
135 }
136
137 # DEPENDENCIES = [MACRO]:[library/header]:[GIT REPO]
138 DEPENDENCIES = {
139 'AC_CHECK_LIB': {'mapper': 'phosphor-objmgr'},
Matthew Barth710f3f02017-01-18 15:20:19 -0600140 'AC_CHECK_HEADER': {
141 'host-ipmid': 'phosphor-host-ipmid',
142 'sdbusplus': 'sdbusplus',
143 'log.hpp': 'phosphor-logging'
Patrick Williamseab8a372017-01-30 11:21:32 -0600144 },
145 'PKG_CHECK_MODULES': {
Matthew Barth19e261e2017-02-01 12:55:22 -0600146 'phosphor-dbus-interfaces': 'phosphor-dbus-interfaces',
147 'sdbusplus': 'sdbusplus'
Matthew Barth710f3f02017-01-18 15:20:19 -0600148 }
Matthew Barthccb7f852016-11-23 17:43:02 -0600149 }
150
Matthew Barth33df8792016-12-19 14:30:17 -0600151 # Set command line arguments
152 parser = argparse.ArgumentParser()
153 parser.add_argument("-w", "--workspace", dest="WORKSPACE", required=True,
154 help="Workspace directory location(i.e. /home)")
155 parser.add_argument("-p", "--package", dest="PACKAGE", required=True,
156 help="OpenBMC package to be unit tested")
157 parser.add_argument("-v", "--verbose", action="store_true",
158 help="Print additional package status messages")
159 args = parser.parse_args(sys.argv[1:])
160 WORKSPACE = args.WORKSPACE
161 UNIT_TEST_PKG = args.PACKAGE
162 if args.verbose:
163 def printline(*line):
164 for arg in line:
165 print arg,
166 print
167 else:
168 printline = lambda *l: None
Matthew Barthccb7f852016-11-23 17:43:02 -0600169
170 prev_umask = os.umask(000)
171 # Determine dependencies and install them
172 dep_installed = dict()
173 dep_installed[UNIT_TEST_PKG] = False
174 dep_installed = build_depends(UNIT_TEST_PKG,
175 os.path.join(WORKSPACE, UNIT_TEST_PKG),
176 dep_installed)
177 os.chdir(os.path.join(WORKSPACE, UNIT_TEST_PKG))
178 # Run package unit tests
Matthew Barth33df8792016-12-19 14:30:17 -0600179 check_call_cmd(os.path.join(WORKSPACE, UNIT_TEST_PKG), 'make', 'check')
Matthew Barthccb7f852016-11-23 17:43:02 -0600180 os.umask(prev_umask)