149 lines
5.3 KiB
Python
Executable File
149 lines
5.3 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
import argparse
|
|
import os
|
|
import sys
|
|
import subprocess
|
|
|
|
SRC_MOUNT = "/root/src"
|
|
|
|
|
|
class PodmanImageBuilder:
|
|
"""Builds the podman image for Floss build environment."""
|
|
|
|
def __init__(self, workdir, rootdir, tag):
|
|
""" Constructor.
|
|
|
|
Args:
|
|
workdir: Working directory for this script. Dockerfile should exist here.
|
|
rootdir: Root directory for Bluetooth.
|
|
tag: Label in format |name:version|.
|
|
"""
|
|
self.workdir = workdir
|
|
self.rootdir = rootdir
|
|
(self.name, self.version) = tag.split(':')
|
|
self.build_tag = '{}:{}'.format(self.name, 'buildtemp')
|
|
self.container_name = 'floss-buildtemp'
|
|
self.final_tag = tag
|
|
self.env = os.environ.copy()
|
|
|
|
# Mark dpkg builders for podman
|
|
self.env['LIBCHROME_DOCKER'] = '1'
|
|
self.env['MODP_DOCKER'] = '1'
|
|
|
|
def run_command(self, target, args, cwd=None, env=None, ignore_rc=False):
|
|
""" Run command and stream the output.
|
|
"""
|
|
# Set some defaults
|
|
if not cwd:
|
|
cwd = self.workdir
|
|
if not env:
|
|
env = self.env
|
|
|
|
rc = 0
|
|
process = subprocess.Popen(args, cwd=cwd, env=env, stdout=subprocess.PIPE)
|
|
while True:
|
|
line = process.stdout.readline()
|
|
print(line.decode('utf-8'), end="")
|
|
if not line:
|
|
rc = process.poll()
|
|
if rc is not None:
|
|
break
|
|
|
|
time.sleep(0.1)
|
|
|
|
if rc != 0 and not ignore_rc:
|
|
raise Exception("{} failed. Return code is {}".format(target, rc))
|
|
|
|
def _podman_build(self):
|
|
self.run_command('podman build', ['podman', 'build', '-t', self.build_tag, '.'])
|
|
|
|
def _build_dpkg_and_commit(self):
|
|
# Try to remove any previous instance of the container that may be
|
|
# running if this script didn't complete cleanly last time.
|
|
self.run_command('podman stop', ['podman', 'stop', '-t', '1', self.container_name], ignore_rc=True)
|
|
self.run_command('podman rm', ['podman', 'rm', self.container_name], ignore_rc=True)
|
|
|
|
# Runs never terminating application on the newly built image in detached mode
|
|
mount_str = 'type=bind,src={},dst={},readonly'.format(self.rootdir, SRC_MOUNT)
|
|
self.run_command('podman run', [
|
|
'podman', 'run', '--name', self.container_name, '--mount', mount_str, '-d', self.build_tag, 'tail', '-f',
|
|
'/dev/null'
|
|
])
|
|
|
|
commands = [
|
|
# Create the output directories
|
|
['mkdir', '-p', '/tmp/libchrome', '/tmp/modpb64'],
|
|
|
|
# Run the dpkg builder for modp_b64
|
|
[f'{SRC_MOUNT}/system/build/dpkg/modp_b64/gen-src-pkg.sh', '/tmp/modpb64'],
|
|
|
|
# Install modp_b64 since libchrome depends on it
|
|
['find', '/tmp/modpb64', '-name', 'modp*.deb', '-exec', 'dpkg', '-i', '{}', '+'],
|
|
|
|
# Run the dpkg builder for libchrome
|
|
[f'{SRC_MOUNT}/system/build/dpkg/libchrome/gen-src-pkg.sh', '/tmp/libchrome'],
|
|
|
|
# Install libchrome.
|
|
['find', '/tmp/libchrome', '-name', 'libchrome_*.deb', '-exec', 'dpkg', '-i', '{}', '+'],
|
|
|
|
# Delete intermediate files
|
|
['rm', '-rf', '/tmp/libchrome', '/tmp/modpb64'],
|
|
]
|
|
|
|
try:
|
|
# Run commands in container first to install everything.
|
|
for i, cmd in enumerate(commands):
|
|
self.run_command('podman exec #{}'.format(i), ['podman', 'exec', '-it', self.container_name] + cmd)
|
|
|
|
# Commit changes into the final tag name
|
|
self.run_command('podman commit', ['podman', 'commit', self.container_name, self.final_tag])
|
|
finally:
|
|
# Stop running the container and remove it
|
|
self.run_command('podman stop', ['podman', 'stop', '-t', '1', self.container_name])
|
|
self.run_command('podman rm', ['podman', 'rm', self.container_name])
|
|
|
|
def _check_podman_runnable(self):
|
|
try:
|
|
subprocess.check_output(['podman', 'ps'], stderr=subprocess.STDOUT)
|
|
except subprocess.CalledProcessError as err:
|
|
if 'denied' in err.output.decode('utf-8'):
|
|
print('Run script as sudo')
|
|
else:
|
|
print('Unexpected error: {}'.format(err.output.decode('utf-8')))
|
|
|
|
return False
|
|
|
|
# No exception means podman is ok
|
|
return True
|
|
|
|
def build(self):
|
|
if not self._check_podman_runnable():
|
|
return
|
|
|
|
# First build the podman image
|
|
self._podman_build()
|
|
|
|
# Then build libchrome and modp-b64 inside the podman image and install
|
|
# them. Commit those changes to the final label.
|
|
self._build_dpkg_and_commit()
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description='Build podman image for Floss build environment.')
|
|
parser.add_argument('--tag', required=True, help='Tag for podman image. i.e. floss:latest')
|
|
args = parser.parse_args()
|
|
|
|
# cwd should be set to same directory as this script (that's where Dockerfile
|
|
# is kept).
|
|
workdir = os.path.dirname(os.path.abspath(sys.argv[0]))
|
|
rootdir = os.path.abspath(os.path.join(workdir, '../..'))
|
|
|
|
# Build the podman image
|
|
pib = PodmanImageBuilder(workdir, rootdir, args.tag)
|
|
pib.build()
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|