blob: 96e01d3f7cdff5e95e314442e844808f94221c1d [file] [log] [blame]
Mirko Bonadeiea4e3992021-04-14 18:05:29 +00001#!/usr/bin/env python3
brettw@chromium.org67bb8612013-11-08 20:51:40 +00002# 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.
brettw@chromium.org67bb8612013-11-08 20:51:40 +00005"""This script is a wrapper around the GN binary that is pulled from Google
6Cloud Storage when you sync Chrome. The binaries go into platform-specific
7subdirectories in the source tree.
8
9This script makes there be one place for forwarding to the correct platform's
10binary. It will also automatically try to find the gn binary when run inside
11the chrome source tree, so users can just type "gn" on the command line
12(normally depot_tools is on the path)."""
13
Raul Tambre80ee78e2019-05-06 22:41:05 +000014from __future__ import print_function
15
Nico Weber09e0b382019-03-11 16:54:07 +000016import gclient_paths
brettw@chromium.org67bb8612013-11-08 20:51:40 +000017import os
18import subprocess
19import sys
20
21
Sergiy Byelozyorov01489552018-06-29 18:13:15 +000022def PruneVirtualEnv():
Mike Frysinger124bb8e2023-09-06 05:48:55 +000023 # Set by VirtualEnv, no need to keep it.
24 os.environ.pop('VIRTUAL_ENV', None)
Sergiy Byelozyorov01489552018-06-29 18:13:15 +000025
Mike Frysinger124bb8e2023-09-06 05:48:55 +000026 # Set by VPython, if scripts want it back they have to set it explicitly.
27 os.environ.pop('PYTHONNOUSERSITE', None)
Sergiy Byelozyorov01489552018-06-29 18:13:15 +000028
Mike Frysinger124bb8e2023-09-06 05:48:55 +000029 # Look for "activate_this.py" in this path, which is installed by
30 # VirtualEnv. This mechanism is used by vpython as well to sanitize
31 # VirtualEnvs from $PATH.
32 os.environ['PATH'] = os.pathsep.join([
33 p for p in os.environ.get('PATH', '').split(os.pathsep)
34 if not os.path.isfile(os.path.join(p, 'activate_this.py'))
35 ])
Sergiy Byelozyorov01489552018-06-29 18:13:15 +000036
37
Junji Watanabec5505882023-09-25 01:32:45 +000038def findGnInPath():
39 env_path = os.getenv('PATH')
40 if not env_path:
41 return
42 exe = 'gn'
43 if sys.platform in ('win32', 'cygwin'):
44 exe += '.exe'
45 for bin_dir in env_path.split(os.pathsep):
46 if bin_dir.rstrip(os.sep).endswith('depot_tools'):
47 # skip depot_tools to avoid calling gn.py infinitely.
48 continue
49 gn_path = os.path.join(bin_dir, exe)
50 if os.path.isfile(gn_path):
51 return gn_path
52
53
brettw@chromium.org67bb8612013-11-08 20:51:40 +000054def main(args):
Mike Frysinger124bb8e2023-09-06 05:48:55 +000055 # Prune all evidence of VPython/VirtualEnv out of the environment. This
56 # means that we 'unwrap' vpython VirtualEnv path/env manipulation.
57 # Invocations of `python` from GN should never inherit the gn.py's own
58 # VirtualEnv. This also helps to ensure that generated ninja files do not
59 # reference python.exe from the VirtualEnv generated from depot_tools' own
60 # .vpython file (or lack thereof), but instead reference the default python
61 # from the PATH.
62 PruneVirtualEnv()
Sergiy Byelozyorov01489552018-06-29 18:13:15 +000063
Mike Frysinger124bb8e2023-09-06 05:48:55 +000064 # Try in primary solution location first, with the gn binary having been
65 # downloaded by cipd in the projects DEPS.
66 primary_solution_path = gclient_paths.GetPrimarySolutionPath()
67 if primary_solution_path:
68 gn_path = os.path.join(primary_solution_path, 'third_party', 'gn',
69 'gn' + gclient_paths.GetExeSuffix())
70 if os.path.exists(gn_path):
71 return subprocess.call([gn_path] + args[1:])
Scott Grahama991ac62018-06-26 23:19:51 +000072
Mike Frysinger124bb8e2023-09-06 05:48:55 +000073 # Otherwise try the old .sha1 and download_from_google_storage locations
74 # inside of buildtools.
75 bin_path = gclient_paths.GetBuildtoolsPlatformBinaryPath()
76 if not bin_path:
Junji Watanabec5505882023-09-25 01:32:45 +000077 gn_path = findGnInPath()
78 if gn_path:
79 return subprocess.call([gn_path] + args[1:])
Mike Frysinger124bb8e2023-09-06 05:48:55 +000080 print(
81 'gn.py: Could not find checkout in any parent of the current '
82 'path.\nThis must be run inside a checkout.',
83 file=sys.stderr)
84 return 1
85 gn_path = os.path.join(bin_path, 'gn' + gclient_paths.GetExeSuffix())
86 if not os.path.exists(gn_path):
87 print('gn.py: Could not find gn executable at: %s' % gn_path,
88 file=sys.stderr)
89 return 2
90 return subprocess.call([gn_path] + args[1:])
brettw@chromium.org67bb8612013-11-08 20:51:40 +000091
nick@chromium.org3ac1c4e2014-01-16 02:44:42 +000092
brettw@chromium.org67bb8612013-11-08 20:51:40 +000093if __name__ == '__main__':
Mike Frysinger124bb8e2023-09-06 05:48:55 +000094 try:
95 sys.exit(main(sys.argv))
96 except KeyboardInterrupt:
97 sys.stderr.write('interrupted\n')
98 sys.exit(1)