您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

93 行
2.4KB

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