ninja.py 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. #!/usr/bin/env python3
  2. # Copyright 2022 The Chromium Authors. All rights reserved.
  3. # Use of this source code is governed by a BSD-style license that can be
  4. # found in the LICENSE file.
  5. """This script is a wrapper around the ninja binary that is pulled to
  6. third_party as part of gclient sync. It will automatically find the ninja
  7. binary when run inside a gclient source tree, so users can just type
  8. "ninja" on the command line."""
  9. import os
  10. import subprocess
  11. import sys
  12. import gclient_paths
  13. def findNinjaInPath():
  14. env_path = os.getenv('PATH')
  15. if not env_path:
  16. return
  17. exe = 'ninja'
  18. if sys.platform in ['win32', 'cygwin']:
  19. exe += '.exe'
  20. for bin_dir in env_path.split(os.pathsep):
  21. if bin_dir.rstrip(os.sep).endswith('depot_tools'):
  22. # skip depot_tools to avoid calling ninja.py infitely.
  23. continue
  24. ninja_path = os.path.join(bin_dir, exe)
  25. if os.path.isfile(ninja_path):
  26. return ninja_path
  27. def fallback(ninja_args):
  28. # Try to find ninja in PATH.
  29. ninja_path = findNinjaInPath()
  30. if ninja_path:
  31. return subprocess.call([ninja_path] + ninja_args)
  32. print(
  33. 'depot_tools/ninja.py: Could not find Ninja in the third_party of '
  34. 'the current project, nor in your PATH.\n'
  35. 'Please take one of the following actions to install Ninja:\n'
  36. '- If your project has DEPS, add a CIPD Ninja dependency to DEPS.\n'
  37. '- Otherwise, add Ninja to your PATH *after* depot_tools.',
  38. file=sys.stderr)
  39. return 1
  40. def main(args):
  41. # On Windows the ninja.bat script passes along the arguments enclosed in
  42. # double quotes. This prevents multiple levels of parsing of the special '^'
  43. # characters needed when compiling a single file. When this case is
  44. # detected, we need to split the argument. This means that arguments
  45. # containing actual spaces are not supported by ninja.bat, but that is not a
  46. # real limitation.
  47. if (sys.platform.startswith('win') and len(args) == 2):
  48. args = args[:1] + args[1].split()
  49. # macOS's python sets CPATH, LIBRARY_PATH, SDKROOT implicitly.
  50. # https://openradar.appspot.com/radar?id=5608755232243712
  51. #
  52. # Removing those environment variables to avoid affecting clang's behaviors.
  53. if sys.platform == 'darwin':
  54. os.environ.pop("CPATH", None)
  55. os.environ.pop("LIBRARY_PATH", None)
  56. os.environ.pop("SDKROOT", None)
  57. # Get gclient root + src.
  58. primary_solution_path = gclient_paths.GetPrimarySolutionPath()
  59. gclient_root_path = gclient_paths.FindGclientRoot(os.getcwd())
  60. gclient_src_root_path = None
  61. if gclient_root_path:
  62. gclient_src_root_path = os.path.join(gclient_root_path, 'src')
  63. for base_path in set(
  64. [primary_solution_path, gclient_root_path, gclient_src_root_path]):
  65. if not base_path:
  66. continue
  67. ninja_path = os.path.join(base_path, 'third_party', 'ninja',
  68. 'ninja' + gclient_paths.GetExeSuffix())
  69. if os.path.isfile(ninja_path):
  70. return subprocess.call([ninja_path] + args[1:])
  71. return fallback(args[1:])
  72. if __name__ == '__main__':
  73. try:
  74. sys.exit(main(sys.argv))
  75. except KeyboardInterrupt:
  76. sys.exit(1)