/ docker / lakesoul-python-wheel-build-env / build_docker_image.py
build_docker_image.py
  1  # SPDX-FileCopyrightText: 2023 LakeSoul Contributors
  2  #
  3  # SPDX-License-Identifier: Apache-2.0
  4  
  5  import io
  6  import os
  7  import re
  8  import json
  9  import subprocess
 10  
 11  
 12  class ManylinuxDockerImageBuilder(object):
 13      def __init__(self):
 14          self._dockerfile_dir = self._get_dockerfile_dir()
 15          self._project_root_dir = self._get_project_root_dir()
 16          self._pyproject_toml_path = self._get_pyproject_toml_path()
 17          self._manylinux_image_name = self._get_manylinux_image_name()
 18  
 19      def _get_dockerfile_dir(self):
 20          dir_path = os.path.dirname(os.path.realpath(__file__))
 21          return dir_path
 22  
 23      def _get_project_root_dir(self):
 24          dir_path = os.path.dirname(os.path.realpath(__file__))
 25          dir_path = os.path.dirname(os.path.dirname(dir_path))
 26          return dir_path
 27  
 28      def _get_pyproject_toml_path(self):
 29          file_path = os.path.join(self._project_root_dir, "pyproject.toml")
 30          return file_path
 31  
 32      def _get_manylinux_image_name(self):
 33          with io.open(self._pyproject_toml_path) as fin:
 34              text = fin.read()
 35          match = re.search('^manylinux-x86_64-image = "(.+)"$', text, re.M)
 36          if match is None:
 37              message = "fail to read manylinux image name "
 38              message += "from %r" % self._pyproject_toml_path
 39              raise RuntimeError(message)
 40          image_name = match.group(1)
 41          return image_name
 42  
 43      def _parse_args(self):
 44          import argparse
 45  
 46          parser = argparse.ArgumentParser(description="build manylinux docker image")
 47          parser.add_argument(
 48              "-f",
 49              "--force-rebuild",
 50              action="store_true",
 51              help="force rebuilding of the docker image",
 52          )
 53          args = parser.parse_args()
 54          self._force_rebuild = args.force_rebuild
 55  
 56      def _docker_image_exists(self):
 57          args = ["docker", "images", "--format", "json"]
 58          output = subprocess.check_output(args)
 59          for line in output.splitlines():
 60              image = json.loads(line)
 61              name = "%s:%s" % (image["Repository"], image["Tag"])
 62              if name == self._manylinux_image_name:
 63                  return True
 64          return False
 65  
 66      def _handle_proxy(self, args):
 67          import os
 68  
 69          http_proxy = os.environ.get("http_proxy")
 70          https_proxy = os.environ.get("https_proxy")
 71          no_proxy = os.environ.get("no_proxy")
 72          if http_proxy is not None or https_proxy is not None or no_proxy is not None:
 73              args += ["--network", "host"]
 74              if http_proxy is not None:
 75                  args += ["--build-arg", "http_proxy=%s" % http_proxy]
 76              if https_proxy is not None:
 77                  args += ["--build-arg", "https_proxy=%s" % https_proxy]
 78              if no_proxy is not None:
 79                  args += ["--build-arg", "no_proxy=%s" % no_proxy]
 80  
 81      def _handle_rust_version(self, args):
 82          print(self._project_root_dir)
 83          with open(f"{self._project_root_dir}/rust/rust-toolchain.toml") as f:
 84              match = re.search(r'channel\s*=\s*"([^"]+)"', f.read())
 85              if match:
 86                  channel_value = match.group(1)
 87                  args += ["--build-arg", "RUST_VRESION=%s" % channel_value]
 88              else:
 89                  raise RuntimeError("get rust version failed")
 90  
 91      def _build_docker_image(self):
 92          args = ["docker", "build"]
 93          self._handle_proxy(args)
 94          self._handle_rust_version(args)
 95          args += ["--tag", self._manylinux_image_name]
 96          args += [self._dockerfile_dir]
 97          subprocess.check_call(args)
 98  
 99      def run(self):
100          self._parse_args()
101          if not self._docker_image_exists() or self._force_rebuild:
102              self._build_docker_image()
103  
104  
105  def main():
106      builder = ManylinuxDockerImageBuilder()
107      builder.run()
108  
109  
110  if __name__ == "__main__":
111      main()