gn.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. #!/usr/bin/env python3
  2. # Copyright 2013 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 GN binary that is pulled from Google
  6. Cloud Storage when you sync Chrome. The binaries go into platform-specific
  7. subdirectories in the source tree.
  8. This script makes there be one place for forwarding to the correct platform's
  9. binary. It will also automatically try to find the gn binary when run inside
  10. the chrome source tree, so users can just type "gn" on the command line
  11. (normally depot_tools is on the path)."""
  12. import gclient_paths
  13. import os
  14. import subprocess
  15. import sys
  16. def PruneVirtualEnv():
  17. # Set by VirtualEnv, no need to keep it.
  18. os.environ.pop('VIRTUAL_ENV', None)
  19. # Set by VPython, if scripts want it back they have to set it explicitly.
  20. os.environ.pop('PYTHONNOUSERSITE', None)
  21. # Look for "activate_this.py" in this path, which is installed by
  22. # VirtualEnv. This mechanism is used by vpython as well to sanitize
  23. # VirtualEnvs from $PATH.
  24. os.environ['PATH'] = os.pathsep.join([
  25. p for p in os.environ.get('PATH', '').split(os.pathsep)
  26. if not os.path.isfile(os.path.join(p, 'activate_this.py'))
  27. ])
  28. def findGnInPath():
  29. env_path = os.getenv('PATH')
  30. if not env_path:
  31. return
  32. exe = 'gn'
  33. if sys.platform in ('win32', 'cygwin'):
  34. exe += '.exe'
  35. for bin_dir in env_path.split(os.pathsep):
  36. if bin_dir.rstrip(os.sep).endswith('depot_tools'):
  37. # skip depot_tools to avoid calling gn.py infinitely.
  38. continue
  39. gn_path = os.path.join(bin_dir, exe)
  40. if os.path.isfile(gn_path):
  41. return gn_path
  42. def main(args):
  43. # Prune all evidence of VPython/VirtualEnv out of the environment. This
  44. # means that we 'unwrap' vpython VirtualEnv path/env manipulation.
  45. # Invocations of `python` from GN should never inherit the gn.py's own
  46. # VirtualEnv. This also helps to ensure that generated ninja files do not
  47. # reference python.exe from the VirtualEnv generated from depot_tools' own
  48. # .vpython3 file (or lack thereof), but instead reference the default python
  49. # from the PATH.
  50. PruneVirtualEnv()
  51. # Try in primary solution location first, with the gn binary having been
  52. # downloaded by cipd in the projects DEPS.
  53. primary_solution_path = gclient_paths.GetPrimarySolutionPath()
  54. if primary_solution_path:
  55. gn_path = os.path.join(primary_solution_path, 'third_party', 'gn',
  56. 'gn' + gclient_paths.GetExeSuffix())
  57. if os.path.exists(gn_path):
  58. return subprocess.call([gn_path] + args[1:])
  59. # Otherwise try the old .sha1 and download_from_google_storage locations
  60. # inside of buildtools.
  61. bin_path = gclient_paths.GetBuildtoolsPlatformBinaryPath()
  62. if not bin_path:
  63. gn_path = findGnInPath()
  64. if gn_path:
  65. return subprocess.call([gn_path] + args[1:])
  66. print(
  67. 'gn.py: Could not find checkout in any parent of the current '
  68. 'path.\nThis must be run inside a checkout.',
  69. file=sys.stderr)
  70. return 1
  71. # TODO(b/328065301): Once chromium/src CL has landed to migrate
  72. # buildtools/<platform>/gn to buildtools/<platform>/gn/gn, only return
  73. # gn/gn path.
  74. old_gn_path = os.path.join(bin_path, 'gn' + gclient_paths.GetExeSuffix())
  75. new_gn_path = os.path.join(bin_path, 'gn',
  76. 'gn' + gclient_paths.GetExeSuffix())
  77. paths = [new_gn_path, old_gn_path]
  78. for path in paths:
  79. if os.path.isfile(path):
  80. return subprocess.call([path] + args[1:])
  81. print('gn.py: Could not find gn executable at: %s' % paths, file=sys.stderr)
  82. return 2
  83. if __name__ == '__main__':
  84. try:
  85. sys.exit(main(sys.argv))
  86. except KeyboardInterrupt:
  87. sys.stderr.write('interrupted\n')
  88. sys.exit(1)