You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. import argparse
  2. from pathlib import Path
  3. import subprocess
  4. import os
  5. from typing import Sequence
  6. import sys
  7. import shutil
  8. BOOTSTRAP_PHASES = [
  9. 'bootstrap-p1',
  10. 'bootstrap-p2',
  11. ]
  12. HERE = Path(__file__).parent.absolute()
  13. PROJECT_ROOT = HERE.parent
  14. BUILD_DIR = PROJECT_ROOT / '_build'
  15. BOOTSTRAP_DIR = BUILD_DIR / '_bootstrap'
  16. PREBUILT_DIR = PROJECT_ROOT / '_prebuilt'
  17. def _run_quiet(args) -> None:
  18. cmd = [str(s) for s in args]
  19. res = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
  20. if res.returncode != 0:
  21. print(f'Subprocess command {cmd} failed '
  22. f'[{res.returncode}]:\n{res.stdout.decode()}')
  23. raise subprocess.CalledProcessError(res.returncode, cmd)
  24. def _clone_bootstrap_phase(ph: str) -> None:
  25. print(f'Cloning: {ph}')
  26. if BOOTSTRAP_DIR.exists():
  27. shutil.rmtree(BOOTSTRAP_DIR)
  28. _run_quiet([
  29. 'git',
  30. 'clone',
  31. '--depth=1',
  32. f'--branch={ph}',
  33. f'file://{PROJECT_ROOT}',
  34. BOOTSTRAP_DIR,
  35. ])
  36. def _build_bootstrap_phase(ph: str, args: argparse.Namespace) -> None:
  37. print(f'Running build: {ph} (Please wait a moment...)')
  38. env = os.environ.copy()
  39. env['DDS_BOOTSTRAP_PREV_EXE'] = PREBUILT_DIR / 'dds'
  40. subprocess.check_call(
  41. [
  42. sys.executable,
  43. str(BOOTSTRAP_DIR / 'tools/build.py'),
  44. f'--cxx={args.cxx}',
  45. ],
  46. env=env,
  47. )
  48. def _pull_executable() -> Path:
  49. prebuild_dir = (PROJECT_ROOT / '_prebuilt')
  50. prebuild_dir.mkdir(exist_ok=True)
  51. exe, = list(BOOTSTRAP_DIR.glob('_build/dds*'))
  52. dest = prebuild_dir / exe.name
  53. exe.rename(dest)
  54. return dest
  55. def _run_boot_phase(phase: str, args: argparse.Namespace) -> Path:
  56. _clone_bootstrap_phase(phase)
  57. _build_bootstrap_phase(phase, args)
  58. return _pull_executable()
  59. def main(argv: Sequence[str]) -> int:
  60. parser = argparse.ArgumentParser()
  61. parser.add_argument(
  62. '--cxx', help='The C++ compiler to use for the build', required=True)
  63. args = parser.parse_args(argv)
  64. for phase in BOOTSTRAP_PHASES:
  65. exe = _run_boot_phase(phase, args)
  66. print(f'A bootstrapped DDS executable has been generated: {exe}')
  67. return 0
  68. if __name__ == "__main__":
  69. sys.exit(main(sys.argv[1:]))