Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(256)

Side by Side Diff: pylib/gyp/generator/ninja.py

Issue 9358067: Very preliminary work for ninja on Windows (Closed) Base URL: http://gyp.googlecode.com/svn/trunk/
Patch Set: Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « gyptest.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 import gyp 5 import gyp
6 import gyp.common 6 import gyp.common
7 import gyp.system_test 7 import gyp.system_test
8 import gyp.xcode_emulation 8 import gyp.xcode_emulation
9 import os.path 9 import os.path
10 import re 10 import re
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
69 """Given a relative path like foo/bar, return the inverse relative path: 69 """Given a relative path like foo/bar, return the inverse relative path:
70 the path from the relative path back to the origin dir. 70 the path from the relative path back to the origin dir.
71 71
72 E.g. os.path.normpath(os.path.join(path, InvertRelativePath(path))) 72 E.g. os.path.normpath(os.path.join(path, InvertRelativePath(path)))
73 should always produce the empty string.""" 73 should always produce the empty string."""
74 74
75 if not path: 75 if not path:
76 return path 76 return path
77 # Only need to handle relative paths into subdirectories for now. 77 # Only need to handle relative paths into subdirectories for now.
78 assert '..' not in path, path 78 assert '..' not in path, path
79 depth = len(path.split('/')) 79 depth = len(path.split(os.path.sep))
80 return '/'.join(['..'] * depth) 80 return '/'.join(['..'] * depth)
81 81
82 82
83 class Target: 83 class Target:
84 """Target represents the paths used within a single gyp target. 84 """Target represents the paths used within a single gyp target.
85 85
86 Conceptually, building a single target A is a series of steps: 86 Conceptually, building a single target A is a series of steps:
87 87
88 1) actions/rules/copies generates source/resources/etc. 88 1) actions/rules/copies generates source/resources/etc.
89 2) compiles generates .o files 89 2) compiles generates .o files
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
173 build_dir: path from source root to build output 173 build_dir: path from source root to build output
174 abs_build_dir: absolute path to the build directory 174 abs_build_dir: absolute path to the build directory
175 """ 175 """
176 176
177 self.target_outputs = target_outputs 177 self.target_outputs = target_outputs
178 self.base_dir = base_dir 178 self.base_dir = base_dir
179 self.build_dir = build_dir 179 self.build_dir = build_dir
180 self.ninja = ninja_syntax.Writer(output_file) 180 self.ninja = ninja_syntax.Writer(output_file)
181 self.flavor = flavor 181 self.flavor = flavor
182 self.abs_build_dir = abs_build_dir 182 self.abs_build_dir = abs_build_dir
183 self.obj_ext = '.obj' if flavor == 'win' else '.o'
183 184
184 # Relative path from build output dir to base dir. 185 # Relative path from build output dir to base dir.
185 self.build_to_base = os.path.join(InvertRelativePath(build_dir), base_dir) 186 self.build_to_base = os.path.join(InvertRelativePath(build_dir), base_dir)
186 # Relative path from base dir to build dir. 187 # Relative path from base dir to build dir.
187 self.base_to_build = os.path.join(InvertRelativePath(base_dir), build_dir) 188 self.base_to_build = os.path.join(InvertRelativePath(base_dir), build_dir)
188 189
189 def ExpandSpecial(self, path, product_dir=None): 190 def ExpandSpecial(self, path, product_dir=None):
190 """Expand specials like $!PRODUCT_DIR in |path|. 191 """Expand specials like $!PRODUCT_DIR in |path|.
191 192
192 If |product_dir| is None, assumes the cwd is already the product 193 If |product_dir| is None, assumes the cwd is already the product
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
341 # Write out the compilation steps, if any. 342 # Write out the compilation steps, if any.
342 link_deps = [] 343 link_deps = []
343 sources = spec.get('sources', []) + extra_sources 344 sources = spec.get('sources', []) + extra_sources
344 if sources: 345 if sources:
345 link_deps = self.WriteSources( 346 link_deps = self.WriteSources(
346 config_name, config, sources, compile_depends_stamp, 347 config_name, config, sources, compile_depends_stamp,
347 gyp.xcode_emulation.MacPrefixHeader( 348 gyp.xcode_emulation.MacPrefixHeader(
348 self.xcode_settings, self.GypPathToNinja, 349 self.xcode_settings, self.GypPathToNinja,
349 lambda path, lang: self.GypPathToUniqueOutput(path + '-' + lang))) 350 lambda path, lang: self.GypPathToUniqueOutput(path + '-' + lang)))
350 # Some actions/rules output 'sources' that are already object files. 351 # Some actions/rules output 'sources' that are already object files.
351 link_deps += [self.GypPathToNinja(f) for f in sources if f.endswith('.o')] 352 link_deps += [self.GypPathToNinja(f)
353 for f in sources if f.endswith(self.obj_ext)]
352 354
353 # Write out a link step, if needed. 355 # Write out a link step, if needed.
354 output = None 356 output = None
355 if link_deps or self.target.actions_stamp or actions_depends: 357 if link_deps or self.target.actions_stamp or actions_depends:
356 output = self.WriteTarget(spec, config_name, config, link_deps, 358 output = self.WriteTarget(spec, config_name, config, link_deps,
357 self.target.actions_stamp or actions_depends) 359 self.target.actions_stamp or actions_depends)
358 if self.is_mac_bundle: 360 if self.is_mac_bundle:
359 mac_bundle_depends.append(output) 361 mac_bundle_depends.append(output)
360 362
361 # Bundle all of the above together, if needed. 363 # Bundle all of the above together, if needed.
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after
620 elif ext in ('c', 's', 'S'): 622 elif ext in ('c', 's', 'S'):
621 command = 'cc' 623 command = 'cc'
622 elif self.flavor == 'mac' and ext == 'm': 624 elif self.flavor == 'mac' and ext == 'm':
623 command = 'objc' 625 command = 'objc'
624 elif self.flavor == 'mac' and ext == 'mm': 626 elif self.flavor == 'mac' and ext == 'mm':
625 command = 'objcxx' 627 command = 'objcxx'
626 else: 628 else:
627 # TODO: should we assert here on unexpected extensions? 629 # TODO: should we assert here on unexpected extensions?
628 continue 630 continue
629 input = self.GypPathToNinja(source) 631 input = self.GypPathToNinja(source)
630 output = self.GypPathToUniqueOutput(filename + '.o') 632 output = self.GypPathToUniqueOutput(filename + self.obj_ext)
631 implicit = precompiled_header.GetObjDependencies([input], [output]) 633 implicit = precompiled_header.GetObjDependencies([input], [output])
632 self.ninja.build(output, command, input, 634 self.ninja.build(output, command, input,
633 implicit=[gch for _, _, gch in implicit], 635 implicit=[gch for _, _, gch in implicit],
634 order_only=predepends) 636 order_only=predepends)
635 outputs.append(output) 637 outputs.append(output)
636 638
637 self.WritePchTargets(pch_commands) 639 self.WritePchTargets(pch_commands)
638 640
639 self.ninja.newline() 641 self.ninja.newline()
640 return outputs 642 return outputs
(...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after
959 import gyp.generator.xcode as xcode_generator 961 import gyp.generator.xcode as xcode_generator
960 global generator_additional_non_configuration_keys 962 global generator_additional_non_configuration_keys
961 generator_additional_non_configuration_keys = getattr(xcode_generator, 963 generator_additional_non_configuration_keys = getattr(xcode_generator,
962 'generator_additional_non_configuration_keys', []) 964 'generator_additional_non_configuration_keys', [])
963 global generator_additional_path_sections 965 global generator_additional_path_sections
964 generator_additional_path_sections = getattr(xcode_generator, 966 generator_additional_path_sections = getattr(xcode_generator,
965 'generator_additional_path_sections', []) 967 'generator_additional_path_sections', [])
966 global generator_extra_sources_for_rules 968 global generator_extra_sources_for_rules
967 generator_extra_sources_for_rules = getattr(xcode_generator, 969 generator_extra_sources_for_rules = getattr(xcode_generator,
968 'generator_extra_sources_for_rules', []) 970 'generator_extra_sources_for_rules', [])
971 elif flavor == 'win':
972 default_variables.setdefault('EXECUTABLE_SUFFIX', '.exe')
973 default_variables.setdefault('STATIC_LIB_PREFIX', '')
974 default_variables.setdefault('STATIC_LIB_SUFFIX', '.lib')
975 default_variables.setdefault('SHARED_LIB_PREFIX', '')
976 default_variables.setdefault('SHARED_LIB_SUFFIX', '.dll')
969 else: 977 else:
970 operating_system = flavor 978 operating_system = flavor
971 if flavor == 'android': 979 if flavor == 'android':
972 operating_system = 'linux' # Keep this legacy behavior for now. 980 operating_system = 'linux' # Keep this legacy behavior for now.
973 default_variables.setdefault('OS', operating_system) 981 default_variables.setdefault('OS', operating_system)
974 default_variables.setdefault('SHARED_LIB_SUFFIX', '.so') 982 default_variables.setdefault('SHARED_LIB_SUFFIX', '.so')
975 default_variables.setdefault('SHARED_LIB_DIR', '$!PRODUCT_DIR/lib') 983 default_variables.setdefault('SHARED_LIB_DIR', '$!PRODUCT_DIR/lib')
976 default_variables.setdefault('LIB_DIR', '') 984 default_variables.setdefault('LIB_DIR', '')
977 985
978 986
(...skipping 18 matching lines...) Expand all
997 config_name) 1005 config_name)
998 1006
999 master_ninja = ninja_syntax.Writer( 1007 master_ninja = ninja_syntax.Writer(
1000 OpenOutput(os.path.join(options.toplevel_dir, build_dir, 'build.ninja')), 1008 OpenOutput(os.path.join(options.toplevel_dir, build_dir, 'build.ninja')),
1001 width=120) 1009 width=120)
1002 1010
1003 # Put build-time support tools in out/{config_name}. 1011 # Put build-time support tools in out/{config_name}.
1004 gyp.common.CopyTool(flavor, os.path.join(options.toplevel_dir, build_dir)) 1012 gyp.common.CopyTool(flavor, os.path.join(options.toplevel_dir, build_dir))
1005 1013
1006 # Grab make settings for CC/CXX. 1014 # Grab make settings for CC/CXX.
1007 cc, cxx = 'gcc', 'g++' 1015 if flavor == 'win':
1016 cc = cxx = 'cl'
1017 else:
1018 cc, cxx = 'gcc', 'g++'
1008 build_file, _, _ = gyp.common.ParseQualifiedTarget(target_list[0]) 1019 build_file, _, _ = gyp.common.ParseQualifiedTarget(target_list[0])
1009 make_global_settings = data[build_file].get('make_global_settings', []) 1020 make_global_settings = data[build_file].get('make_global_settings', [])
1010 build_to_root = InvertRelativePath(build_dir) 1021 build_to_root = InvertRelativePath(build_dir)
1011 for key, value in make_global_settings: 1022 for key, value in make_global_settings:
1012 if key == 'CC': cc = os.path.join(build_to_root, value) 1023 if key == 'CC': cc = os.path.join(build_to_root, value)
1013 if key == 'CXX': cxx = os.path.join(build_to_root, value) 1024 if key == 'CXX': cxx = os.path.join(build_to_root, value)
1014 1025
1015 flock = 'flock' 1026 flock = 'flock'
1016 if flavor == 'mac': 1027 if flavor == 'mac':
1017 flock = './gyp-mac-tool flock' 1028 flock = './gyp-mac-tool flock'
1018 master_ninja.variable('cc', os.environ.get('CC', cc)) 1029 master_ninja.variable('cc', os.environ.get('CC', cc))
1019 master_ninja.variable('cxx', os.environ.get('CXX', cxx)) 1030 master_ninja.variable('cxx', os.environ.get('CXX', cxx))
1020 master_ninja.variable('ld', flock + ' linker.lock $cxx') 1031 if flavor == 'win':
1032 master_ninja.variable('ld', 'link')
1033 else:
1034 master_ninja.variable('ld', flock + ' linker.lock $cxx')
1021 master_ninja.variable('cc_host', '$cc') 1035 master_ninja.variable('cc_host', '$cc')
1022 master_ninja.variable('cxx_host', '$cxx') 1036 master_ninja.variable('cxx_host', '$cxx')
1023 if flavor == 'mac': 1037 if flavor == 'mac':
1024 master_ninja.variable('mac_tool', os.path.join('.', 'gyp-mac-tool')) 1038 master_ninja.variable('mac_tool', os.path.join('.', 'gyp-mac-tool'))
1025 master_ninja.newline() 1039 master_ninja.newline()
1026 1040
1027 master_ninja.rule( 1041 if flavor != 'win':
1028 'cc', 1042 master_ninja.rule(
1029 description='CC $out', 1043 'cc',
1030 command=('$cc -MMD -MF $out.d $defines $includes $cflags $cflags_c ' 1044 description='CC $out',
1031 '$cflags_pch_c -c $in -o $out'), 1045 command=('$cc -MMD -MF $out.d $defines $includes $cflags $cflags_c '
1032 depfile='$out.d') 1046 '$cflags_pch_c -c $in -o $out'),
1033 master_ninja.rule( 1047 depfile='$out.d')
1034 'cxx', 1048 master_ninja.rule(
1035 description='CXX $out', 1049 'cxx',
1036 command=('$cxx -MMD -MF $out.d $defines $includes $cflags $cflags_cc ' 1050 description='CXX $out',
1037 '$cflags_pch_cc -c $in -o $out'), 1051 command=('$cxx -MMD -MF $out.d $defines $includes $cflags $cflags_cc '
1038 depfile='$out.d') 1052 '$cflags_pch_cc -c $in -o $out'),
1039 if flavor != 'mac': 1053 depfile='$out.d')
1054 else:
1055 # TODO(scottmg): Decide how /showIncludes handling should work in ninja.
1056 master_ninja.rule(
1057 'cc',
1058 description='CC $out',
1059 command=('$cc /nologo $defines $includes $cflags $cflags_c '
1060 '$cflags_pch_c /c $in /Fo$out'),
1061 depfile='$out.d')
1062 master_ninja.rule(
1063 'cxx',
1064 description='CXX $out',
1065 command=('$cxx /nologo $defines $includes $cflags $cflags_cc '
1066 '$cflags_pch_cc /c $in /Fo$out'),
1067 depfile='$out.d')
1068
1069 if flavor != 'mac' and flavor != 'win':
1040 master_ninja.rule( 1070 master_ninja.rule(
1041 'alink', 1071 'alink',
1042 description='AR $out', 1072 description='AR $out',
1043 command='rm -f $out && ar rcsT $out $in') 1073 command='rm -f $out && ar rcsT $out $in')
1044 master_ninja.rule( 1074 master_ninja.rule(
1045 'solink', 1075 'solink',
1046 description='SOLINK $out', 1076 description='SOLINK $out',
1047 command=('$ld -shared $ldflags -o $out -Wl,-soname=$soname ' 1077 command=('$ld -shared $ldflags -o $out -Wl,-soname=$soname '
1048 '-Wl,--whole-archive $in -Wl,--no-whole-archive $libs')) 1078 '-Wl,--whole-archive $in -Wl,--no-whole-archive $libs'))
1049 master_ninja.rule( 1079 master_ninja.rule(
1050 'solink_module', 1080 'solink_module',
1051 description='SOLINK(module) $out', 1081 description='SOLINK(module) $out',
1052 command=('$ld -shared $ldflags -o $out -Wl,-soname=$soname ' 1082 command=('$ld -shared $ldflags -o $out -Wl,-soname=$soname '
1053 '-Wl,--start-group $in -Wl,--end-group $libs')) 1083 '-Wl,--start-group $in -Wl,--end-group $libs'))
1054 master_ninja.rule( 1084 master_ninja.rule(
1055 'link', 1085 'link',
1056 description='LINK $out', 1086 description='LINK $out',
1057 command=('$ld $ldflags -o $out -Wl,-rpath=\$$ORIGIN/lib ' 1087 command=('$ld $ldflags -o $out -Wl,-rpath=\$$ORIGIN/lib '
1058 '-Wl,--start-group $in -Wl,--end-group $libs')) 1088 '-Wl,--start-group $in -Wl,--end-group $libs'))
1089 elif flavor == 'win':
1090 master_ninja.rule(
1091 'alink',
1092 description='AR $out',
1093 command='lib /nologo /OUT:$out.lib $in')
1094 master_ninja.rule(
1095 'solink',
1096 description='SOLINK $out',
1097 command=('$ld /nologo /DLL $ldflags /OUT:$out.dll $in $libs'))
1098 master_ninja.rule(
1099 'solink_module',
1100 description='SOLINK(module) $out',
1101 command=('$ld /nologo /DLL $ldflags /OUT:$out.dll $in $libs'))
1102 master_ninja.rule(
1103 'link',
1104 description='LINK $out',
1105 command=('$ld /nologo $ldflags /OUT:$out.exe $in $libs'))
1059 else: 1106 else:
1060 master_ninja.rule( 1107 master_ninja.rule(
1061 'objc', 1108 'objc',
1062 description='OBJC $out', 1109 description='OBJC $out',
1063 command=('$cc -MMD -MF $out.d $defines $includes $cflags $cflags_objc ' 1110 command=('$cc -MMD -MF $out.d $defines $includes $cflags $cflags_objc '
1064 '$cflags_pch_objc -c $in -o $out'), 1111 '$cflags_pch_objc -c $in -o $out'),
1065 depfile='$out.d') 1112 depfile='$out.d')
1066 master_ninja.rule( 1113 master_ninja.rule(
1067 'objcxx', 1114 'objcxx',
1068 description='OBJCXX $out', 1115 description='OBJCXX $out',
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1103 command='$env $mac_tool $mactool_cmd $in $out') 1150 command='$env $mac_tool $mactool_cmd $in $out')
1104 master_ninja.rule( 1151 master_ninja.rule(
1105 'package_framework', 1152 'package_framework',
1106 description='PACKAGE FRAMEWORK $out, POSTBUILDS', 1153 description='PACKAGE FRAMEWORK $out, POSTBUILDS',
1107 command='$mac_tool package-framework $out $version$postbuilds ' 1154 command='$mac_tool package-framework $out $version$postbuilds '
1108 '&& touch $out') 1155 '&& touch $out')
1109 master_ninja.rule( 1156 master_ninja.rule(
1110 'stamp', 1157 'stamp',
1111 description='STAMP $out', 1158 description='STAMP $out',
1112 command='${postbuilds}touch $out') 1159 command='${postbuilds}touch $out')
1113 master_ninja.rule( 1160 if flavor == 'win':
1114 'copy', 1161 # TODO(scottmg): Copy fallback?
1115 description='COPY $in $out', 1162 master_ninja.rule(
1116 command='ln -f $in $out 2>/dev/null || (rm -rf $out && cp -af $in $out)') 1163 'copy',
1164 description='COPY $in $out',
1165 command='mklink /h $out $in >nul')
1166 else:
1167 master_ninja.rule(
1168 'copy',
1169 description='COPY $in $out',
1170 command='ln -f $in $out 2>/dev/null || (rm -rf $out && cp -af $in $out)')
1117 master_ninja.newline() 1171 master_ninja.newline()
1118 1172
1119 all_targets = set() 1173 all_targets = set()
1120 for build_file in params['build_files']: 1174 for build_file in params['build_files']:
1121 for target in gyp.common.AllTargets(target_list, target_dicts, build_file): 1175 for target in gyp.common.AllTargets(target_list, target_dicts, build_file):
1122 all_targets.add(target) 1176 all_targets.add(target)
1123 all_outputs = set() 1177 all_outputs = set()
1124 1178
1125 # target_outputs is a map from qualified target name to a Target object. 1179 # target_outputs is a map from qualified target name to a Target object.
1126 target_outputs = {} 1180 target_outputs = {}
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1169 1223
1170 user_config = params.get('generator_flags', {}).get('config', None) 1224 user_config = params.get('generator_flags', {}).get('config', None)
1171 if user_config: 1225 if user_config:
1172 GenerateOutputForConfig(target_list, target_dicts, data, params, 1226 GenerateOutputForConfig(target_list, target_dicts, data, params,
1173 user_config) 1227 user_config)
1174 else: 1228 else:
1175 config_names = target_dicts[target_list[0]]['configurations'].keys() 1229 config_names = target_dicts[target_list[0]]['configurations'].keys()
1176 for config_name in config_names: 1230 for config_name in config_names:
1177 GenerateOutputForConfig(target_list, target_dicts, data, params, 1231 GenerateOutputForConfig(target_list, target_dicts, data, params,
1178 config_name) 1232 config_name)
OLDNEW
« no previous file with comments | « gyptest.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698