build-docs.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. #! /usr/bin/env python3
  2. '''
  3. Builds MuPDF docs.
  4. * Takes care of using a venv and installing required packages and running
  5. `sphinx-build`.
  6. * Works on Unix and Windows.
  7. * Currently only builds HTML docs.
  8. * Arguments are handled in the order in which they occur on the command line.
  9. * Generated docs start at: build/docs/html/index.html
  10. Args:
  11. build:
  12. Build docs:
  13. * Create and enter a Python venv.
  14. * Install packages as specified in file `docs/src/requirements.txt`.
  15. * Run `sphinx-build`.
  16. clean:
  17. Removes generated directory.
  18. -h
  19. --help
  20. Show this help.
  21. --pip 0|1
  22. If 0, we do not create the venv or install packages into it. Instead we
  23. assume that the venv has already been created and contains the required
  24. Python packages. This runs slightly faster.
  25. If no args are given, we do `build`.
  26. Example timings:
  27. 60s Clean build (including creating venv and installing packages).
  28. 10s Rebuild with no changes.
  29. 3.3s Rebuild with no changes and --pip 0.
  30. '''
  31. import shutil
  32. import os
  33. import platform
  34. import subprocess
  35. import sys
  36. def main():
  37. pip = True
  38. if len(sys.argv) == 1:
  39. sys.argv.append('build')
  40. args = iter(sys.argv[1:])
  41. while 1:
  42. try:
  43. arg = next(args)
  44. except StopIteration:
  45. break
  46. if arg in ('-h', '--help'):
  47. print(__doc__.strip())
  48. elif arg == 'clean':
  49. print(f'Removing: {dir_out}')
  50. shutil.rmtree(dir_out, ignore_errors=True)
  51. elif arg == 'build':
  52. build(pip)
  53. elif arg == '--pip':
  54. pip = int(next(args))
  55. def build(pip):
  56. windows = platform.system() == 'Windows'
  57. openbsd = platform.system() == 'OpenBSD'
  58. macos = platform.system() == 'Darwin'
  59. root = os.path.relpath(os.path.abspath(f'{__file__}/../..'))
  60. dir_in = f'{root}/docs/src'
  61. dir_out = f'{root}/build/docs'
  62. dir_venv = f'{root}/build/docs/venv'
  63. # We construct a command that does everything we need to do.
  64. #
  65. command = 'true'
  66. # Create venv.
  67. #
  68. print(f'Using Python venv: {dir_venv}')
  69. if pip:
  70. command += f' && {sys.executable} -m venv {dir_venv}'
  71. else:
  72. assert os.path.isdir(dir_venv), f'Python venv directory does not exist: {dir_venv}'
  73. # Activate the venv.
  74. #
  75. if windows:
  76. # Most of the time we can use `/` on Windows, but for activating a venv
  77. # we need to use `os.sep`.
  78. command += f' && ./{dir_venv}/Scripts/activate'.replace('/', os.sep)
  79. else:
  80. command += f' && . {dir_venv}/bin/activate'
  81. # Install required packages.
  82. #
  83. if pip:
  84. command += f' && python -m pip install --upgrade pip'
  85. command += f' && python -m pip install'
  86. with open(f'{dir_in}/requirements.txt') as f:
  87. for line in f:
  88. package = line.strip()
  89. if package.startswith('#') or not package:
  90. continue
  91. if (openbsd or macos) and package == 'rst2pdf':
  92. print(f'Not installing on OpenBSD/MacOS because install fails: {package}')
  93. continue
  94. command += f' {package}'
  95. # Run sphinx-build.
  96. #
  97. command += f' && sphinx-build -M html {dir_in} {dir_out}'
  98. # Run command.
  99. #
  100. print(f'Running command: {command}')
  101. sys.stdout.flush()
  102. subprocess.run(command, shell=True, check=True)
  103. print(f'')
  104. print(f'sphinx-build succeeded.')
  105. print(f'Have built documentation:')
  106. print(f' {dir_out}/html/index.html')
  107. if __name__ == '__main__':
  108. main()