| OLD | NEW |
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 | 2 |
| 3 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 3 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 4 # Use of this source code is governed by a BSD-style license that can be | 4 # Use of this source code is governed by a BSD-style license that can be |
| 5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
| 6 | 6 |
| 7 # This script is wrapper for Chromium that adds some support for how GYP | 7 # This script is wrapper for Chromium that adds some support for how GYP |
| 8 # is invoked by Chromium beyond what can be done in the gclient hooks. | 8 # is invoked by Chromium beyond what can be done in the gclient hooks. |
| 9 | 9 |
| 10 import glob | 10 import glob |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 92 key = FormatKeyForGN(tokens[0]) | 92 key = FormatKeyForGN(tokens[0]) |
| 93 if len(tokens) == 2: | 93 if len(tokens) == 2: |
| 94 result += [(key, tokens[1])] | 94 result += [(key, tokens[1])] |
| 95 else: | 95 else: |
| 96 # No value supplied, treat it as a boolean and set it. Note that we | 96 # No value supplied, treat it as a boolean and set it. Note that we |
| 97 # use the string '1' here so we have a consistent definition whether | 97 # use the string '1' here so we have a consistent definition whether |
| 98 # you do 'foo=1' or 'foo'. | 98 # you do 'foo=1' or 'foo'. |
| 99 result += [(key, '1')] | 99 result += [(key, '1')] |
| 100 return result | 100 return result |
| 101 | 101 |
| 102 |
| 102 def GetGypVarsForGN(supplemental_files): | 103 def GetGypVarsForGN(supplemental_files): |
| 103 """Returns a dictionary of all GYP vars that we will be passing to GN.""" | 104 """Returns a dictionary of all GYP vars that we will be passing to GN.""" |
| 105 # Find the .gyp directory in the user's home directory. |
| 106 home_dot_gyp = os.environ.get('GYP_CONFIG_DIR', None) |
| 107 if home_dot_gyp: |
| 108 home_dot_gyp = os.path.expanduser(home_dot_gyp) |
| 109 if not home_dot_gyp: |
| 110 home_vars = ['HOME'] |
| 111 if sys.platform in ('cygwin', 'win32'): |
| 112 home_vars.append('USERPROFILE') |
| 113 for home_var in home_vars: |
| 114 home = os.getenv(home_var) |
| 115 if home != None: |
| 116 home_dot_gyp = os.path.join(home, '.gyp') |
| 117 if not os.path.exists(home_dot_gyp): |
| 118 home_dot_gyp = None |
| 119 else: |
| 120 break |
| 121 |
| 122 if home_dot_gyp: |
| 123 include_gypi = os.path.join(home_dot_gyp, "include.gypi") |
| 124 if os.path.exists(include_gypi): |
| 125 supplemental_files += [include_gypi] |
| 104 | 126 |
| 105 # GYP defines from the supplemental.gypi files. | 127 # GYP defines from the supplemental.gypi files. |
| 106 supp_items = [] | 128 supp_items = [] |
| 107 for supplement in supplemental_files: | 129 for supplement in supplemental_files: |
| 108 with open(supplement, 'r') as f: | 130 with open(supplement, 'r') as f: |
| 109 try: | 131 try: |
| 110 file_data = eval(f.read(), {'__builtins__': None}, None) | 132 file_data = eval(f.read(), {'__builtins__': None}, None) |
| 111 except SyntaxError, e: | 133 except SyntaxError, e: |
| 112 e.filename = os.path.abspath(supplement) | 134 e.filename = os.path.abspath(supplement) |
| 113 raise | 135 raise |
| 114 variables = file_data.get('variables', []) | 136 variables = file_data.get('variables', []) |
| 115 for v in variables: | 137 for v in variables: |
| 116 supp_items += [(FormatKeyForGN(v), str(variables[v]))] | 138 supp_items += [(FormatKeyForGN(v), str(variables[v]))] |
| 117 | 139 |
| 118 # GYP defines from the environment. | 140 # GYP defines from the environment. |
| 119 env_items = ProcessGypDefinesItems( | 141 env_items = ProcessGypDefinesItems( |
| 120 shlex.split(os.environ.get('GYP_DEFINES', ''))) | 142 shlex.split(os.environ.get('GYP_DEFINES', ''))) |
| 121 | 143 |
| 122 # GYP defines from the command line. We can't use optparse since we want | 144 # GYP defines from the command line. We can't use optparse since we want |
| 123 # to ignore all arguments other than "-D". | 145 # to ignore all arguments other than "-D". |
| 124 cmdline_input_items = [] | 146 cmdline_input_items = [] |
| 125 for i in range(len(sys.argv))[1:]: | 147 for i in range(len(sys.argv))[1:]: |
| 126 if sys.argv[i].startswith('-D'): | 148 if sys.argv[i].startswith('-D'): |
| 127 if sys.argv[i] == '-D' and i + 1 < len(sys.argv): | 149 if sys.argv[i] == '-D' and i + 1 < len(sys.argv): |
| 128 cmdline_input_items += [sys.argv[i + 1]] | 150 cmdline_input_items += [sys.argv[i + 1]] |
| 129 elif len(sys.argv[i]) > 2: | 151 elif len(sys.argv[i]) > 2: |
| 130 cmdline_input_items += [sys.argv[i][2:]] | 152 cmdline_input_items += [sys.argv[i][2:]] |
| 131 cmdline_items = ProcessGypDefinesItems(cmdline_input_items) | 153 cmdline_items = ProcessGypDefinesItems(cmdline_input_items) |
| 132 | 154 |
| 133 return dict(supp_items + env_items + cmdline_items) | 155 vars_dict = dict(supp_items + env_items + cmdline_items) |
| 156 # It's not possible to set a default value for cpu_arch in GN, so do it here |
| 157 # for now (http://crbug.com/344767). |
| 158 if vars_dict.get('OS') == 'android' and not 'target_arch' in vars_dict: |
| 159 vars_dict['target_arch'] = 'arm' |
| 160 return vars_dict |
| 161 |
| 134 | 162 |
| 135 def GetOutputDirectory(): | 163 def GetOutputDirectory(): |
| 136 """Returns the output directory that GYP will use.""" | 164 """Returns the output directory that GYP will use.""" |
| 137 # GYP generator flags from the command line. We can't use optparse since we | 165 # GYP generator flags from the command line. We can't use optparse since we |
| 138 # want to ignore all arguments other than "-G". | 166 # want to ignore all arguments other than "-G". |
| 139 needle = '-Goutput_dir=' | 167 needle = '-Goutput_dir=' |
| 140 cmdline_input_items = [] | 168 cmdline_input_items = [] |
| 141 for item in sys.argv[1:]: | 169 for item in sys.argv[1:]: |
| 142 if item.startswith(needle): | 170 if item.startswith(needle): |
| 143 return item[len(needle):] | 171 return item[len(needle):] |
| 144 | 172 |
| 145 env_items = shlex.split(os.environ.get('GYP_GENERATOR_FLAGS', '')) | 173 env_items = shlex.split(os.environ.get('GYP_GENERATOR_FLAGS', '')) |
| 146 needle = 'output_dir=' | 174 needle = 'output_dir=' |
| 147 for item in env_items: | 175 for item in env_items: |
| 148 if item.startswith(needle): | 176 if item.startswith(needle): |
| 149 return item[len(needle):] | 177 return item[len(needle):] |
| 150 | 178 |
| 151 return "out" | 179 return "out" |
| 152 | 180 |
| 153 def GetArgsStringForGN(supplemental_files): | 181 |
| 182 def GetArgsStringForGN(vars_dict): |
| 154 """Returns the args to pass to GN. | 183 """Returns the args to pass to GN. |
| 155 Based on a subset of the GYP variables that have been rewritten a bit.""" | 184 Based on a subset of the GYP variables that have been rewritten a bit.""" |
| 156 | |
| 157 # Find the .gyp directory in the user's home directory. | |
| 158 home_dot_gyp = os.environ.get('GYP_CONFIG_DIR', None) | |
| 159 if home_dot_gyp: | |
| 160 home_dot_gyp = os.path.expanduser(home_dot_gyp) | |
| 161 if not home_dot_gyp: | |
| 162 home_vars = ['HOME'] | |
| 163 if sys.platform in ('cygwin', 'win32'): | |
| 164 home_vars.append('USERPROFILE') | |
| 165 for home_var in home_vars: | |
| 166 home = os.getenv(home_var) | |
| 167 if home != None: | |
| 168 home_dot_gyp = os.path.join(home, '.gyp') | |
| 169 if not os.path.exists(home_dot_gyp): | |
| 170 home_dot_gyp = None | |
| 171 else: | |
| 172 break | |
| 173 | |
| 174 if home_dot_gyp: | |
| 175 include_gypi = os.path.join(home_dot_gyp, "include.gypi") | |
| 176 if os.path.exists(include_gypi): | |
| 177 supplemental_files += [include_gypi] | |
| 178 | |
| 179 vars_dict = GetGypVarsForGN(supplemental_files) | |
| 180 # It's not possible to let set a default value for cpu_arch in GN, so do it | |
| 181 # here for now (http://crbug.com/344767). | |
| 182 if vars_dict.get('OS') == 'android' and not 'target_arch' in vars_dict: | |
| 183 vars_dict['target_arch'] = 'arm' | |
| 184 | |
| 185 gn_args = '' | 185 gn_args = '' |
| 186 | 186 |
| 187 # Note: These are the additional flags passed to various builds by builders | 187 # Note: These are the additional flags passed to various builds by builders |
| 188 # on the main waterfall. We'll probably need to add these at some point: | 188 # on the main waterfall. We'll probably need to add these at some point: |
| 189 # mac_strip_release=1 http://crbug.com/330301 | 189 # mac_strip_release=1 http://crbug.com/330301 |
| 190 # linux_dump_symbols=0 http://crbug.com/330300 | 190 # linux_dump_symbols=0 http://crbug.com/330300 |
| 191 # host_os=linux Probably can skip, GN knows the host OS. | 191 # host_os=linux Probably can skip, GN knows the host OS. |
| 192 # order_text_section=<path> http://crbug.com/330299 | 192 # order_text_section=<path> http://crbug.com/330299 |
| 193 # chromium_win_pch=0 http://crbug.com/297678 | 193 # chromium_win_pch=0 http://crbug.com/297678 |
| 194 # chromium_ios_signing=0 http://crbug.com/330302 | 194 # chromium_ios_signing=0 http://crbug.com/330302 |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 293 # Always include common.gypi. | 293 # Always include common.gypi. |
| 294 AddInclude(os.path.join(script_dir, 'common.gypi')) | 294 AddInclude(os.path.join(script_dir, 'common.gypi')) |
| 295 | 295 |
| 296 # Optionally add supplemental .gypi files if present. | 296 # Optionally add supplemental .gypi files if present. |
| 297 for supplement in supplemental_files: | 297 for supplement in supplemental_files: |
| 298 AddInclude(supplement) | 298 AddInclude(supplement) |
| 299 | 299 |
| 300 return result | 300 return result |
| 301 | 301 |
| 302 | 302 |
| 303 def RunGN(supplemental_includes): | 303 def RunGN(vars_dict): |
| 304 """Runs GN, returning True if it succeeded, printing an error and returning | 304 """Runs GN, returning True if it succeeded, printing an error and returning |
| 305 false if not.""" | 305 false if not.""" |
| 306 | 306 |
| 307 # The binaries in platform-specific subdirectories in src/tools/gn/bin. | 307 # The binaries in platform-specific subdirectories in src/tools/gn/bin. |
| 308 gnpath = SRC_DIR + '/tools/gn/bin/' | 308 gnpath = SRC_DIR + '/tools/gn/bin/' |
| 309 if sys.platform in ('cygwin', 'win32'): | 309 if sys.platform in ('cygwin', 'win32'): |
| 310 gnpath += 'win/gn.exe' | 310 gnpath += 'win/gn.exe' |
| 311 elif sys.platform.startswith('linux'): | 311 elif sys.platform.startswith('linux'): |
| 312 # On Linux we have 32-bit and 64-bit versions. | 312 # On Linux we have 32-bit and 64-bit versions. |
| 313 if subprocess.check_output(["getconf", "LONG_BIT"]).find("64") >= 0: | 313 if subprocess.check_output(["getconf", "LONG_BIT"]).find("64") >= 0: |
| 314 gnpath += 'linux/gn' | 314 gnpath += 'linux/gn' |
| 315 else: | 315 else: |
| 316 gnpath += 'linux/gn32' | 316 gnpath += 'linux/gn32' |
| 317 elif sys.platform == 'darwin': | 317 elif sys.platform == 'darwin': |
| 318 gnpath += 'mac/gn' | 318 gnpath += 'mac/gn' |
| 319 else: | 319 else: |
| 320 print 'Unknown platform for GN: ', sys.platform | 320 print 'Unknown platform for GN: ', sys.platform |
| 321 return False | 321 return False |
| 322 | 322 |
| 323 print 'Generating gyp files from GN...' | 323 print 'Generating gyp files from GN...' |
| 324 | 324 |
| 325 # Need to pass both the source root (the bots don't run this command from | 325 # Need to pass both the source root (the bots don't run this command from |
| 326 # within the source tree) as well as set the is_gyp value so the BUILD files | 326 # within the source tree) as well as set the is_gyp value so the BUILD files |
| 327 # to know they're being run under GYP. | 327 # to know they're being run under GYP. |
| 328 args = [gnpath, 'gyp', '-q', | 328 args = [gnpath, 'gyp', '-q', |
| 329 '--root=' + chrome_src, | 329 '--root=' + chrome_src, |
| 330 '--args=' + GetArgsStringForGN(supplemental_includes), | 330 '--args=' + GetArgsStringForGN(vars_dict), |
| 331 '--output=//' + GetOutputDirectory() + '/gn_build/'] | 331 '--output=//' + GetOutputDirectory() + '/gn_build/'] |
| 332 return subprocess.call(args) == 0 | 332 return subprocess.call(args) == 0 |
| 333 | 333 |
| 334 | 334 |
| 335 def CopyVsRuntimeDlls(output_dir, runtime_dirs): | 335 def CopyVsRuntimeDlls(output_dir, runtime_dirs): |
| 336 """Copies the VS runtime DLLs from the given |runtime_dirs| to the output | 336 """Copies the VS runtime DLLs from the given |runtime_dirs| to the output |
| 337 directory so that even if not system-installed, built binaries are likely to | 337 directory so that even if not system-installed, built binaries are likely to |
| 338 be able to run. | 338 be able to run. |
| 339 | 339 |
| 340 This needs to be run after gyp has been run so that the expected target | 340 This needs to be run after gyp has been run so that the expected target |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 472 print('Using automatic toolchain in %s (%s edition).' % ( | 472 print('Using automatic toolchain in %s (%s edition).' % ( |
| 473 toolchain, 'Pro' if version_is_pro else 'Express')) | 473 toolchain, 'Pro' if version_is_pro else 'Express')) |
| 474 | 474 |
| 475 # If CHROMIUM_GYP_SYNTAX_CHECK is set to 1, it will invoke gyp with --check | 475 # If CHROMIUM_GYP_SYNTAX_CHECK is set to 1, it will invoke gyp with --check |
| 476 # to enfore syntax checking. | 476 # to enfore syntax checking. |
| 477 syntax_check = os.environ.get('CHROMIUM_GYP_SYNTAX_CHECK') | 477 syntax_check = os.environ.get('CHROMIUM_GYP_SYNTAX_CHECK') |
| 478 if syntax_check and int(syntax_check): | 478 if syntax_check and int(syntax_check): |
| 479 args.append('--check') | 479 args.append('--check') |
| 480 | 480 |
| 481 supplemental_includes = GetSupplementalFiles() | 481 supplemental_includes = GetSupplementalFiles() |
| 482 if not RunGN(supplemental_includes): | 482 gn_vars_dict = GetGypVarsForGN(supplemental_includes) |
| 483 |
| 484 # Automatically turn on crosscompile support for platforms that need it. |
| 485 # (The Chrome OS build sets CC_host / CC_target which implicitly enables |
| 486 # this mode.) |
| 487 if all(('ninja' in os.environ.get('GYP_GENERATORS', ''), |
| 488 gn_vars_dict.get('OS') in ['android', 'ios'], |
| 489 'GYP_CROSSCOMPILE' not in os.environ)): |
| 490 os.environ['GYP_CROSSCOMPILE'] = '1' |
| 491 |
| 492 if not RunGN(gn_vars_dict): |
| 483 sys.exit(1) | 493 sys.exit(1) |
| 484 args.extend( | 494 args.extend( |
| 485 ['-I' + i for i in additional_include_files(supplemental_includes, args)]) | 495 ['-I' + i for i in additional_include_files(supplemental_includes, args)]) |
| 486 | 496 |
| 487 args.extend(['-D', 'gyp_output_dir=' + GetOutputDirectory()]) | 497 args.extend(['-D', 'gyp_output_dir=' + GetOutputDirectory()]) |
| 488 | 498 |
| 489 print 'Updating projects from gyp files...' | 499 print 'Updating projects from gyp files...' |
| 490 sys.stdout.flush() | 500 sys.stdout.flush() |
| 491 | 501 |
| 492 # Off we go... | 502 # Off we go... |
| 493 gyp_rc = gyp.main(args) | 503 gyp_rc = gyp.main(args) |
| 494 | 504 |
| 495 # Check for landmines (reasons to clobber the build). This must be run here, | 505 # Check for landmines (reasons to clobber the build). This must be run here, |
| 496 # rather than a separate runhooks step so that any environment modifications | 506 # rather than a separate runhooks step so that any environment modifications |
| 497 # from above are picked up. | 507 # from above are picked up. |
| 498 print 'Running build/landmines.py...' | 508 print 'Running build/landmines.py...' |
| 499 subprocess.check_call( | 509 subprocess.check_call( |
| 500 [sys.executable, os.path.join(script_dir, 'landmines.py')]) | 510 [sys.executable, os.path.join(script_dir, 'landmines.py')]) |
| 501 | 511 |
| 502 if vs2013_runtime_dll_dirs: | 512 if vs2013_runtime_dll_dirs: |
| 503 CopyVsRuntimeDlls(GetOutputDirectory(), vs2013_runtime_dll_dirs) | 513 CopyVsRuntimeDlls(GetOutputDirectory(), vs2013_runtime_dll_dirs) |
| 504 | 514 |
| 505 sys.exit(gyp_rc) | 515 sys.exit(gyp_rc) |
| OLD | NEW |