OLD | NEW |
1 # Copyright (c) 2012 Google Inc. All rights reserved. | 1 # Copyright (c) 2012 Google Inc. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 """ | 5 """ |
6 This module helps emulate Visual Studio 2008 behavior on top of other | 6 This module helps emulate Visual Studio 2008 behavior on top of other |
7 build systems, primarily ninja. | 7 build systems, primarily ninja. |
8 """ | 8 """ |
9 | 9 |
10 import os | 10 import os |
(...skipping 706 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
717 """Format as an 'environment block' directly suitable for CreateProcess. | 717 """Format as an 'environment block' directly suitable for CreateProcess. |
718 Briefly this is a list of key=value\0, terminated by an additional \0. See | 718 Briefly this is a list of key=value\0, terminated by an additional \0. See |
719 CreateProcess documentation for more details.""" | 719 CreateProcess documentation for more details.""" |
720 block = '' | 720 block = '' |
721 nul = '\0' | 721 nul = '\0' |
722 for key, value in envvar_dict.iteritems(): | 722 for key, value in envvar_dict.iteritems(): |
723 block += key + '=' + value + nul | 723 block += key + '=' + value + nul |
724 block += nul | 724 block += nul |
725 return block | 725 return block |
726 | 726 |
| 727 def _ExtractCLPath(output_of_where): |
| 728 """Gets the path to cl.exe based on the output of `where`.""" |
| 729 # Take the first line, as that's the first found in the PATH. |
| 730 return output_of_where.strip().splitlines()[0].strip() |
| 731 |
727 def GenerateEnvironmentFiles(toplevel_build_dir, generator_flags, open_out): | 732 def GenerateEnvironmentFiles(toplevel_build_dir, generator_flags, open_out): |
728 """It's not sufficient to have the absolute path to the compiler, linker, | 733 """It's not sufficient to have the absolute path to the compiler, linker, |
729 etc. on Windows, as those tools rely on .dlls being in the PATH. We also | 734 etc. on Windows, as those tools rely on .dlls being in the PATH. We also |
730 need to support both x86 and x64 compilers within the same build (to support | 735 need to support both x86 and x64 compilers within the same build (to support |
731 msvs_target_platform hackery). Different architectures require a different | 736 msvs_target_platform hackery). Different architectures require a different |
732 compiler binary, and different supporting environment variables (INCLUDE, | 737 compiler binary, and different supporting environment variables (INCLUDE, |
733 LIB, LIBPATH). So, we extract the environment here, wrap all invocations | 738 LIB, LIBPATH). So, we extract the environment here, wrap all invocations |
734 of compiler tools (cl, link, lib, rc, midl, etc.) via win_tool.py which | 739 of compiler tools (cl, link, lib, rc, midl, etc.) via win_tool.py which |
735 sets up the environment, and then we do not prefix the compiler with | 740 sets up the environment, and then we do not prefix the compiler with |
736 an absolute path, instead preferring something like "cl.exe" in the rule | 741 an absolute path, instead preferring something like "cl.exe" in the rule |
737 which will then run whichever the environment setup has put in the path. | 742 which will then run whichever the environment setup has put in the path. |
738 When the following procedure to generate environment files does not | 743 When the following procedure to generate environment files does not |
739 meet your requirement (e.g. for custom toolchains), you can pass | 744 meet your requirement (e.g. for custom toolchains), you can pass |
740 "-G ninja_use_custom_environment_files" to the gyp to suppress file | 745 "-G ninja_use_custom_environment_files" to the gyp to suppress file |
741 generation and use custom environment files prepared by yourself.""" | 746 generation and use custom environment files prepared by yourself.""" |
742 if generator_flags.get('ninja_use_custom_environment_files', 0): | 747 if generator_flags.get('ninja_use_custom_environment_files', 0): |
743 return | 748 return |
744 vs = GetVSVersion(generator_flags) | 749 vs = GetVSVersion(generator_flags) |
| 750 cl_paths = {} |
745 for arch in ('x86', 'x64'): | 751 for arch in ('x86', 'x64'): |
| 752 # Extract environment variables for subprocesses. |
746 args = vs.SetupScript(arch) | 753 args = vs.SetupScript(arch) |
747 args.extend(('&&', 'set')) | 754 args.extend(('&&', 'set')) |
748 popen = subprocess.Popen( | 755 popen = subprocess.Popen( |
749 args, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) | 756 args, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) |
750 variables, _ = popen.communicate() | 757 variables, _ = popen.communicate() |
751 env = _ExtractImportantEnvironment(variables) | 758 env = _ExtractImportantEnvironment(variables) |
752 env_block = _FormatAsEnvironmentBlock(env) | 759 env_block = _FormatAsEnvironmentBlock(env) |
753 f = open_out(os.path.join(toplevel_build_dir, 'environment.' + arch), 'wb') | 760 f = open_out(os.path.join(toplevel_build_dir, 'environment.' + arch), 'wb') |
754 f.write(env_block) | 761 f.write(env_block) |
755 f.close() | 762 f.close() |
756 | 763 |
| 764 # Find cl.exe location for this architecture. |
| 765 args = vs.SetupScript(arch) |
| 766 args.extend(('&&', 'where', 'cl.exe')) |
| 767 popen = subprocess.Popen(args, shell=True, stdout=subprocess.PIPE) |
| 768 output, _ = popen.communicate() |
| 769 cl_paths[arch] = _ExtractCLPath(output) |
| 770 return cl_paths |
| 771 |
757 def VerifyMissingSources(sources, build_dir, generator_flags, gyp_to_ninja): | 772 def VerifyMissingSources(sources, build_dir, generator_flags, gyp_to_ninja): |
758 """Emulate behavior of msvs_error_on_missing_sources present in the msvs | 773 """Emulate behavior of msvs_error_on_missing_sources present in the msvs |
759 generator: Check that all regular source files, i.e. not created at run time, | 774 generator: Check that all regular source files, i.e. not created at run time, |
760 exist on disk. Missing files cause needless recompilation when building via | 775 exist on disk. Missing files cause needless recompilation when building via |
761 VS, and we want this check to match for people/bots that build using ninja, | 776 VS, and we want this check to match for people/bots that build using ninja, |
762 so they're not surprised when the VS build fails.""" | 777 so they're not surprised when the VS build fails.""" |
763 if int(generator_flags.get('msvs_error_on_missing_sources', 0)): | 778 if int(generator_flags.get('msvs_error_on_missing_sources', 0)): |
764 no_specials = filter(lambda x: '$' not in x, sources) | 779 no_specials = filter(lambda x: '$' not in x, sources) |
765 relative = [os.path.join(build_dir, gyp_to_ninja(s)) for s in no_specials] | 780 relative = [os.path.join(build_dir, gyp_to_ninja(s)) for s in no_specials] |
766 missing = filter(lambda x: not os.path.exists(x), relative) | 781 missing = filter(lambda x: not os.path.exists(x), relative) |
767 if missing: | 782 if missing: |
768 # They'll look like out\Release\..\..\stuff\things.cc, so normalize the | 783 # They'll look like out\Release\..\..\stuff\things.cc, so normalize the |
769 # path for a slightly less crazy looking output. | 784 # path for a slightly less crazy looking output. |
770 cleaned_up = [os.path.normpath(x) for x in missing] | 785 cleaned_up = [os.path.normpath(x) for x in missing] |
771 raise Exception('Missing input files:\n%s' % '\n'.join(cleaned_up)) | 786 raise Exception('Missing input files:\n%s' % '\n'.join(cleaned_up)) |
OLD | NEW |