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.

116 lines
3.0KB

  1. import argparse
  2. import os
  3. import sys
  4. from pathlib import Path
  5. from typing import Sequence, NamedTuple
  6. import subprocess
  7. import urllib.request
  8. HERE = Path(__file__).parent.absolute()
  9. TOOLS_DIR = HERE
  10. PROJECT_ROOT = HERE.parent
  11. PREBUILT_DDS = PROJECT_ROOT / '_prebuilt/dds'
  12. class CIOptions(NamedTuple):
  13. cxx: Path
  14. toolchain: str
  15. def _do_bootstrap_build(opts: CIOptions) -> None:
  16. print('Bootstrapping by a local build of prior versions...')
  17. subprocess.check_call([
  18. sys.executable,
  19. '-u',
  20. str(TOOLS_DIR / 'bootstrap.py'),
  21. f'--cxx={opts.cxx}',
  22. ])
  23. def _do_bootstrap_download() -> None:
  24. filename = {
  25. 'win32': 'dds-win-x64.exe',
  26. 'linux': 'dds-linux-x64',
  27. 'darwin': 'dds-macos-x64',
  28. }.get(sys.platform)
  29. if filename is None:
  30. raise RuntimeError(f'We do not have a prebuilt DDS binary for the "{sys.platform}" platform')
  31. url = f'https://github.com/vector-of-bool/dds/releases/download/bootstrap-p2/{filename}'
  32. print(f'Downloading prebuilt DDS executable: {url}')
  33. stream = urllib.request.urlopen(url)
  34. PREBUILT_DDS.parent.mkdir(exist_ok=True, parents=True)
  35. with PREBUILT_DDS.open('wb') as fd:
  36. while True:
  37. buf = stream.read(1024 * 4)
  38. if not buf:
  39. break
  40. fd.write(buf)
  41. if os.name != 'nt':
  42. # Mark the binary executable. By default it won't be
  43. mode = PREBUILT_DDS.stat().st_mode
  44. mode |= 0b001_001_001
  45. PREBUILT_DDS.chmod(mode)
  46. def main(argv: Sequence[str]) -> int:
  47. parser = argparse.ArgumentParser()
  48. parser.add_argument(
  49. '-B',
  50. '--bootstrap-with',
  51. help=
  52. 'Skip the prebuild-bootstrap step. This requires a _prebuilt/dds to exist!',
  53. choices=('download', 'build'),
  54. required=True,
  55. )
  56. parser.add_argument(
  57. '--cxx',
  58. help='The name/path of the C++ compiler to use.',
  59. required=True)
  60. parser.add_argument(
  61. '--toolchain',
  62. '-T',
  63. help='The toolchain to use for the CI process',
  64. required=True)
  65. args = parser.parse_args(argv)
  66. opts = CIOptions(cxx=Path(args.cxx), toolchain=args.toolchain)
  67. if args.bootstrap_with == 'build':
  68. _do_bootstrap_build(opts)
  69. elif args.bootstrap_with == 'download':
  70. _do_bootstrap_download()
  71. else:
  72. assert False, 'impossible'
  73. subprocess.check_call([
  74. str(PREBUILT_DDS),
  75. 'deps',
  76. 'build',
  77. f'-T{opts.toolchain}',
  78. f'--repo-dir={PROJECT_ROOT / "external/repo"}',
  79. ])
  80. subprocess.check_call([
  81. str(PREBUILT_DDS),
  82. 'build',
  83. '--full',
  84. f'-T{opts.toolchain}',
  85. ])
  86. exe_suffix = '.exe' if os.name == 'nt' else ''
  87. subprocess.check_call([
  88. sys.executable,
  89. '-u',
  90. str(TOOLS_DIR / 'test.py'),
  91. f'--exe={PROJECT_ROOT / f"_build/dds{exe_suffix}"}',
  92. f'-T{opts.toolchain}',
  93. ])
  94. return 0
  95. if __name__ == "__main__":
  96. sys.exit(main(sys.argv[1:]))