Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

100 rindas
2.7KB

  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-p4',
  11. ]
  12. HERE = Path(__file__).parent.absolute()
  13. PROJECT_ROOT = HERE.parent
  14. BUILD_DIR = PROJECT_ROOT / '_build'
  15. BOOTSTRAP_BASE_DIR = BUILD_DIR / '_bootstrap'
  16. PREBUILT_DIR = PROJECT_ROOT / '_prebuilt'
  17. EXE_SUFFIX = '.exe' if os.name == 'nt' else ''
  18. def _run_quiet(cmd, **kwargs) -> None:
  19. cmd = [str(s) for s in cmd]
  20. res = subprocess.run(
  21. cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, **kwargs)
  22. if res.returncode != 0:
  23. print(f'Subprocess command {cmd} failed '
  24. f'[{res.returncode}]:\n{res.stdout.decode()}')
  25. raise subprocess.CalledProcessError(res.returncode, cmd)
  26. def _clone_bootstrap_phase(ph: str) -> Path:
  27. print(f'Clone revision: {ph}')
  28. bts_dir = BOOTSTRAP_BASE_DIR / ph
  29. if bts_dir.exists():
  30. shutil.rmtree(bts_dir)
  31. _run_quiet([
  32. 'git',
  33. 'clone',
  34. '--depth=1',
  35. f'--branch={ph}',
  36. f'file://{PROJECT_ROOT}',
  37. bts_dir,
  38. ])
  39. return bts_dir
  40. def _build_bootstrap_phase(ph: str, bts_dir: Path,
  41. args: argparse.Namespace) -> None:
  42. print(f'Build revision: {ph} [This may take a moment]')
  43. env = os.environ.copy()
  44. env['DDS_BOOTSTRAP_PREV_EXE'] = str(PREBUILT_DIR / 'dds')
  45. _run_quiet(
  46. [
  47. sys.executable,
  48. '-u',
  49. str(bts_dir / 'tools/build.py'),
  50. f'--cxx={args.cxx}',
  51. ],
  52. env=env,
  53. cwd=bts_dir,
  54. )
  55. def _pull_executable(bts_dir: Path) -> Path:
  56. prebuild_dir = (PROJECT_ROOT / '_prebuilt')
  57. prebuild_dir.mkdir(exist_ok=True)
  58. generated = list(bts_dir.glob(f'_build/dds{EXE_SUFFIX}'))
  59. assert len(generated) == 1, repr(generated)
  60. exe, = generated
  61. dest = prebuild_dir / exe.name
  62. if dest.exists():
  63. dest.unlink()
  64. exe.rename(dest)
  65. return dest
  66. def _run_boot_phase(phase: str, args: argparse.Namespace) -> Path:
  67. bts_dir = _clone_bootstrap_phase(phase)
  68. _build_bootstrap_phase(phase, bts_dir, args)
  69. return _pull_executable(bts_dir)
  70. def main(argv: Sequence[str]) -> int:
  71. parser = argparse.ArgumentParser()
  72. parser.add_argument(
  73. '--cxx', help='The C++ compiler to use for the build', required=True)
  74. args = parser.parse_args(argv)
  75. for idx, phase in enumerate(BOOTSTRAP_PHASES):
  76. print(f'Bootstrap phase [{idx+1}/{len(BOOTSTRAP_PHASES)}]')
  77. exe = _run_boot_phase(phase, args)
  78. print(f'A bootstrapped DDS executable has been generated: {exe}')
  79. return 0
  80. if __name__ == "__main__":
  81. sys.exit(main(sys.argv[1:]))