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

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 24 matching lines...) Expand all
35 # Special variables that may be used by gyp 'rule' targets. 35 # Special variables that may be used by gyp 'rule' targets.
36 # We generate definitions for these variables on the fly when processing a 36 # We generate definitions for these variables on the fly when processing a
37 # rule. 37 # rule.
38 'RULE_INPUT_ROOT': '${root}', 38 'RULE_INPUT_ROOT': '${root}',
39 'RULE_INPUT_DIRNAME': '${dirname}', 39 'RULE_INPUT_DIRNAME': '${dirname}',
40 'RULE_INPUT_PATH': '${source}', 40 'RULE_INPUT_PATH': '${source}',
41 'RULE_INPUT_EXT': '${ext}', 41 'RULE_INPUT_EXT': '${ext}',
42 'RULE_INPUT_NAME': '${name}', 42 'RULE_INPUT_NAME': '${name}',
43 } 43 }
44 44
45 # TODO(scottmg): This seems wrong, should be based on flavor. How do we push
46 # these back in later?
Evan Martin 2012/02/14 19:07:29 See make.py: def CalculateVariables(default_varia
Nico 2012/02/14 19:14:10 See also the same function in ninja.py :-)
47 if sys.platform == 'win32':
48 generator_default_variables['EXECUTABLE_SUFFIX'] = '.exe'
49 generator_default_variables['STATIC_LIB_PREFIX'] = ''
50 generator_default_variables['STATIC_LIB_SUFFIX'] = '.lib'
51 generator_default_variables['SHARED_LIB_PREFIX'] = ''
52 generator_default_variables['SHARED_LIB_SUFFIX'] = '.dll'
53
45 # TODO: enable cross compiling once we figure out: 54 # TODO: enable cross compiling once we figure out:
46 # - how to not build extra host objects in the non-cross-compile case. 55 # - how to not build extra host objects in the non-cross-compile case.
47 # - how to decide what the host compiler is (should not just be $cc). 56 # - how to decide what the host compiler is (should not just be $cc).
48 # - need ld_host as well. 57 # - need ld_host as well.
49 generator_supports_multiple_toolsets = False 58 generator_supports_multiple_toolsets = False
50 59
51 60
52 def StripPrefix(arg, prefix): 61 def StripPrefix(arg, prefix):
53 if arg.startswith(prefix): 62 if arg.startswith(prefix):
54 return arg[len(prefix):] 63 return arg[len(prefix):]
(...skipping 14 matching lines...) Expand all
69 """Given a relative path like foo/bar, return the inverse relative path: 78 """Given a relative path like foo/bar, return the inverse relative path:
70 the path from the relative path back to the origin dir. 79 the path from the relative path back to the origin dir.
71 80
72 E.g. os.path.normpath(os.path.join(path, InvertRelativePath(path))) 81 E.g. os.path.normpath(os.path.join(path, InvertRelativePath(path)))
73 should always produce the empty string.""" 82 should always produce the empty string."""
74 83
75 if not path: 84 if not path:
76 return path 85 return path
77 # Only need to handle relative paths into subdirectories for now. 86 # Only need to handle relative paths into subdirectories for now.
78 assert '..' not in path, path 87 assert '..' not in path, path
79 depth = len(path.split('/')) 88 depth = len(path.split(os.path.sep))
scottmg 2012/02/14 18:58:48 This was *sneaky*! Paths were ../blah instead of .
Evan Martin 2012/02/14 19:07:29 Is there value in allowing us to generate files ac
80 return '/'.join(['..'] * depth) 89 return '/'.join(['..'] * depth)
81 90
82 91
83 class Target: 92 class Target:
84 """Target represents the paths used within a single gyp target. 93 """Target represents the paths used within a single gyp target.
85 94
86 Conceptually, building a single target A is a series of steps: 95 Conceptually, building a single target A is a series of steps:
87 96
88 1) actions/rules/copies generates source/resources/etc. 97 1) actions/rules/copies generates source/resources/etc.
89 2) compiles generates .o files 98 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 182 build_dir: path from source root to build output
174 abs_build_dir: absolute path to the build directory 183 abs_build_dir: absolute path to the build directory
175 """ 184 """
176 185
177 self.target_outputs = target_outputs 186 self.target_outputs = target_outputs
178 self.base_dir = base_dir 187 self.base_dir = base_dir
179 self.build_dir = build_dir 188 self.build_dir = build_dir
180 self.ninja = ninja_syntax.Writer(output_file) 189 self.ninja = ninja_syntax.Writer(output_file)
181 self.flavor = flavor 190 self.flavor = flavor
182 self.abs_build_dir = abs_build_dir 191 self.abs_build_dir = abs_build_dir
192 self.obj_ext = '.obj' if flavor == 'win' else '.o'
183 193
184 # Relative path from build output dir to base dir. 194 # Relative path from build output dir to base dir.
185 self.build_to_base = os.path.join(InvertRelativePath(build_dir), base_dir) 195 self.build_to_base = os.path.join(InvertRelativePath(build_dir), base_dir)
186 # Relative path from base dir to build dir. 196 # Relative path from base dir to build dir.
187 self.base_to_build = os.path.join(InvertRelativePath(base_dir), build_dir) 197 self.base_to_build = os.path.join(InvertRelativePath(base_dir), build_dir)
188 198
189 def ExpandSpecial(self, path, product_dir=None): 199 def ExpandSpecial(self, path, product_dir=None):
190 """Expand specials like $!PRODUCT_DIR in |path|. 200 """Expand specials like $!PRODUCT_DIR in |path|.
191 201
192 If |product_dir| is None, assumes the cwd is already the product 202 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. 351 # Write out the compilation steps, if any.
342 link_deps = [] 352 link_deps = []
343 sources = spec.get('sources', []) + extra_sources 353 sources = spec.get('sources', []) + extra_sources
344 if sources: 354 if sources:
345 link_deps = self.WriteSources( 355 link_deps = self.WriteSources(
346 config_name, config, sources, compile_depends_stamp, 356 config_name, config, sources, compile_depends_stamp,
347 gyp.xcode_emulation.MacPrefixHeader( 357 gyp.xcode_emulation.MacPrefixHeader(
348 self.xcode_settings, self.GypPathToNinja, 358 self.xcode_settings, self.GypPathToNinja,
349 lambda path, lang: self.GypPathToUniqueOutput(path + '-' + lang))) 359 lambda path, lang: self.GypPathToUniqueOutput(path + '-' + lang)))
350 # Some actions/rules output 'sources' that are already object files. 360 # Some actions/rules output 'sources' that are already object files.
351 link_deps += [self.GypPathToNinja(f) for f in sources if f.endswith('.o')] 361 link_deps += [self.GypPathToNinja(f)
362 for f in sources if f.endswith(self.obj_ext)]
352 363
353 # Write out a link step, if needed. 364 # Write out a link step, if needed.
354 output = None 365 output = None
355 if link_deps or self.target.actions_stamp or actions_depends: 366 if link_deps or self.target.actions_stamp or actions_depends:
356 output = self.WriteTarget(spec, config_name, config, link_deps, 367 output = self.WriteTarget(spec, config_name, config, link_deps,
357 self.target.actions_stamp or actions_depends) 368 self.target.actions_stamp or actions_depends)
358 if self.is_mac_bundle: 369 if self.is_mac_bundle:
359 mac_bundle_depends.append(output) 370 mac_bundle_depends.append(output)
360 371
361 # Bundle all of the above together, if needed. 372 # 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'): 631 elif ext in ('c', 's', 'S'):
621 command = 'cc' 632 command = 'cc'
622 elif self.flavor == 'mac' and ext == 'm': 633 elif self.flavor == 'mac' and ext == 'm':
623 command = 'objc' 634 command = 'objc'
624 elif self.flavor == 'mac' and ext == 'mm': 635 elif self.flavor == 'mac' and ext == 'mm':
625 command = 'objcxx' 636 command = 'objcxx'
626 else: 637 else:
627 # TODO: should we assert here on unexpected extensions? 638 # TODO: should we assert here on unexpected extensions?
628 continue 639 continue
629 input = self.GypPathToNinja(source) 640 input = self.GypPathToNinja(source)
630 output = self.GypPathToUniqueOutput(filename + '.o') 641 output = self.GypPathToUniqueOutput(filename + self.obj_ext)
631 implicit = precompiled_header.GetObjDependencies([input], [output]) 642 implicit = precompiled_header.GetObjDependencies([input], [output])
632 self.ninja.build(output, command, input, 643 self.ninja.build(output, command, input,
633 implicit=[gch for _, _, gch in implicit], 644 implicit=[gch for _, _, gch in implicit],
634 order_only=predepends) 645 order_only=predepends)
635 outputs.append(output) 646 outputs.append(output)
636 647
637 self.WritePchTargets(pch_commands) 648 self.WritePchTargets(pch_commands)
638 649
639 self.ninja.newline() 650 self.ninja.newline()
640 return outputs 651 return outputs
(...skipping 356 matching lines...) Expand 10 before | Expand all | Expand 10 after
997 config_name) 1008 config_name)
998 1009
999 master_ninja = ninja_syntax.Writer( 1010 master_ninja = ninja_syntax.Writer(
1000 OpenOutput(os.path.join(options.toplevel_dir, build_dir, 'build.ninja')), 1011 OpenOutput(os.path.join(options.toplevel_dir, build_dir, 'build.ninja')),
1001 width=120) 1012 width=120)
1002 1013
1003 # Put build-time support tools in out/{config_name}. 1014 # Put build-time support tools in out/{config_name}.
1004 gyp.common.CopyTool(flavor, os.path.join(options.toplevel_dir, build_dir)) 1015 gyp.common.CopyTool(flavor, os.path.join(options.toplevel_dir, build_dir))
1005 1016
1006 # Grab make settings for CC/CXX. 1017 # Grab make settings for CC/CXX.
1007 cc, cxx = 'gcc', 'g++' 1018 if flavor == 'win':
1019 cc = cxx = 'cl'
1020 else:
1021 cc, cxx = 'gcc', 'g++'
1008 build_file, _, _ = gyp.common.ParseQualifiedTarget(target_list[0]) 1022 build_file, _, _ = gyp.common.ParseQualifiedTarget(target_list[0])
1009 make_global_settings = data[build_file].get('make_global_settings', []) 1023 make_global_settings = data[build_file].get('make_global_settings', [])
1010 build_to_root = InvertRelativePath(build_dir) 1024 build_to_root = InvertRelativePath(build_dir)
1011 for key, value in make_global_settings: 1025 for key, value in make_global_settings:
1012 if key == 'CC': cc = os.path.join(build_to_root, value) 1026 if key == 'CC': cc = os.path.join(build_to_root, value)
1013 if key == 'CXX': cxx = os.path.join(build_to_root, value) 1027 if key == 'CXX': cxx = os.path.join(build_to_root, value)
1014 1028
1015 flock = 'flock' 1029 flock = 'flock'
1016 if flavor == 'mac': 1030 if flavor == 'mac':
1017 flock = './gyp-mac-tool flock' 1031 flock = './gyp-mac-tool flock'
1018 master_ninja.variable('cc', os.environ.get('CC', cc)) 1032 master_ninja.variable('cc', os.environ.get('CC', cc))
1019 master_ninja.variable('cxx', os.environ.get('CXX', cxx)) 1033 master_ninja.variable('cxx', os.environ.get('CXX', cxx))
1020 master_ninja.variable('ld', flock + ' linker.lock $cxx') 1034 if flavor == 'win':
1035 master_ninja.variable('ld', 'link')
1036 else:
1037 master_ninja.variable('ld', flock + ' linker.lock $cxx')
1021 master_ninja.variable('cc_host', '$cc') 1038 master_ninja.variable('cc_host', '$cc')
1022 master_ninja.variable('cxx_host', '$cxx') 1039 master_ninja.variable('cxx_host', '$cxx')
1023 if flavor == 'mac': 1040 if flavor == 'mac':
1024 master_ninja.variable('mac_tool', os.path.join('.', 'gyp-mac-tool')) 1041 master_ninja.variable('mac_tool', os.path.join('.', 'gyp-mac-tool'))
1025 master_ninja.newline() 1042 master_ninja.newline()
1026 1043
1027 master_ninja.rule( 1044 if flavor != 'win':
1028 'cc', 1045 master_ninja.rule(
1029 description='CC $out', 1046 'cc',
1030 command=('$cc -MMD -MF $out.d $defines $includes $cflags $cflags_c ' 1047 description='CC $out',
1031 '$cflags_pch_c -c $in -o $out'), 1048 command=('$cc -MMD -MF $out.d $defines $includes $cflags $cflags_c '
1032 depfile='$out.d') 1049 '$cflags_pch_c -c $in -o $out'),
1033 master_ninja.rule( 1050 depfile='$out.d')
1034 'cxx', 1051 master_ninja.rule(
1035 description='CXX $out', 1052 'cxx',
1036 command=('$cxx -MMD -MF $out.d $defines $includes $cflags $cflags_cc ' 1053 description='CXX $out',
1037 '$cflags_pch_cc -c $in -o $out'), 1054 command=('$cxx -MMD -MF $out.d $defines $includes $cflags $cflags_cc '
1038 depfile='$out.d') 1055 '$cflags_pch_cc -c $in -o $out'),
1039 if flavor != 'mac': 1056 depfile='$out.d')
1057 else:
1058 # TODO(scottmg): Decide how /showIncludes handling should work in ninja.
1059 master_ninja.rule(
1060 'cc',
1061 description='CC $out',
1062 command=('$cc /nologo $defines $includes $cflags $cflags_c '
1063 '$cflags_pch_c /c $in /Fo$out'),
1064 depfile='$out.d')
1065 master_ninja.rule(
1066 'cxx',
1067 description='CXX $out',
1068 command=('$cxx /nologo $defines $includes $cflags $cflags_cc '
1069 '$cflags_pch_cc /c $in /Fo$out'),
1070 depfile='$out.d')
1071
1072 if flavor != 'mac' and flavor != 'win':
1040 master_ninja.rule( 1073 master_ninja.rule(
1041 'alink', 1074 'alink',
1042 description='AR $out', 1075 description='AR $out',
1043 command='rm -f $out && ar rcsT $out $in') 1076 command='rm -f $out && ar rcsT $out $in')
1044 master_ninja.rule( 1077 master_ninja.rule(
1045 'solink', 1078 'solink',
1046 description='SOLINK $out', 1079 description='SOLINK $out',
1047 command=('$ld -shared $ldflags -o $out -Wl,-soname=$soname ' 1080 command=('$ld -shared $ldflags -o $out -Wl,-soname=$soname '
1048 '-Wl,--whole-archive $in -Wl,--no-whole-archive $libs')) 1081 '-Wl,--whole-archive $in -Wl,--no-whole-archive $libs'))
1049 master_ninja.rule( 1082 master_ninja.rule(
1050 'solink_module', 1083 'solink_module',
1051 description='SOLINK(module) $out', 1084 description='SOLINK(module) $out',
1052 command=('$ld -shared $ldflags -o $out -Wl,-soname=$soname ' 1085 command=('$ld -shared $ldflags -o $out -Wl,-soname=$soname '
1053 '-Wl,--start-group $in -Wl,--end-group $libs')) 1086 '-Wl,--start-group $in -Wl,--end-group $libs'))
1054 master_ninja.rule( 1087 master_ninja.rule(
1055 'link', 1088 'link',
1056 description='LINK $out', 1089 description='LINK $out',
1057 command=('$ld $ldflags -o $out -Wl,-rpath=\$$ORIGIN/lib ' 1090 command=('$ld $ldflags -o $out -Wl,-rpath=\$$ORIGIN/lib '
1058 '-Wl,--start-group $in -Wl,--end-group $libs')) 1091 '-Wl,--start-group $in -Wl,--end-group $libs'))
1092 elif flavor == 'win':
1093 master_ninja.rule(
1094 'alink',
1095 description='AR $out',
1096 command='lib /nologo /OUT:$out.lib $in')
1097 master_ninja.rule(
1098 'solink',
1099 description='SOLINK $out',
1100 command=('$ld /nologo /DLL $ldflags /OUT:$out.dll $in $libs'))
1101 master_ninja.rule(
1102 'solink_module',
1103 description='SOLINK(module) $out',
1104 command=('$ld /nologo /DLL $ldflags /OUT:$out.dll $in $libs'))
1105 master_ninja.rule(
1106 'link',
1107 description='LINK $out',
1108 command=('$ld /nologo $ldflags /OUT:$out.exe $in $libs'))
1059 else: 1109 else:
1060 master_ninja.rule( 1110 master_ninja.rule(
1061 'objc', 1111 'objc',
1062 description='OBJC $out', 1112 description='OBJC $out',
1063 command=('$cc -MMD -MF $out.d $defines $includes $cflags $cflags_objc ' 1113 command=('$cc -MMD -MF $out.d $defines $includes $cflags $cflags_objc '
1064 '$cflags_pch_objc -c $in -o $out'), 1114 '$cflags_pch_objc -c $in -o $out'),
1065 depfile='$out.d') 1115 depfile='$out.d')
1066 master_ninja.rule( 1116 master_ninja.rule(
1067 'objcxx', 1117 'objcxx',
1068 description='OBJCXX $out', 1118 description='OBJCXX $out',
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1103 command='$env $mac_tool $mactool_cmd $in $out') 1153 command='$env $mac_tool $mactool_cmd $in $out')
1104 master_ninja.rule( 1154 master_ninja.rule(
1105 'package_framework', 1155 'package_framework',
1106 description='PACKAGE FRAMEWORK $out, POSTBUILDS', 1156 description='PACKAGE FRAMEWORK $out, POSTBUILDS',
1107 command='$mac_tool package-framework $out $version$postbuilds ' 1157 command='$mac_tool package-framework $out $version$postbuilds '
1108 '&& touch $out') 1158 '&& touch $out')
1109 master_ninja.rule( 1159 master_ninja.rule(
1110 'stamp', 1160 'stamp',
1111 description='STAMP $out', 1161 description='STAMP $out',
1112 command='${postbuilds}touch $out') 1162 command='${postbuilds}touch $out')
1113 master_ninja.rule( 1163 if flavor == 'win':
1114 'copy', 1164 # TODO(scottmg): Copy fallback?
1115 description='COPY $in $out', 1165 master_ninja.rule(
1116 command='ln -f $in $out 2>/dev/null || (rm -rf $out && cp -af $in $out)') 1166 'copy',
1167 description='COPY $in $out',
1168 command='mklink /h $out $in >nul')
1169 else:
1170 master_ninja.rule(
1171 'copy',
1172 description='COPY $in $out',
1173 command='ln -f $in $out 2>/dev/null || (rm -rf $out && cp -af $in $out)')
1117 master_ninja.newline() 1174 master_ninja.newline()
1118 1175
1119 all_targets = set() 1176 all_targets = set()
1120 for build_file in params['build_files']: 1177 for build_file in params['build_files']:
1121 for target in gyp.common.AllTargets(target_list, target_dicts, build_file): 1178 for target in gyp.common.AllTargets(target_list, target_dicts, build_file):
1122 all_targets.add(target) 1179 all_targets.add(target)
1123 all_outputs = set() 1180 all_outputs = set()
1124 1181
1125 # target_outputs is a map from qualified target name to a Target object. 1182 # target_outputs is a map from qualified target name to a Target object.
1126 target_outputs = {} 1183 target_outputs = {}
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1169 1226
1170 user_config = params.get('generator_flags', {}).get('config', None) 1227 user_config = params.get('generator_flags', {}).get('config', None)
1171 if user_config: 1228 if user_config:
1172 GenerateOutputForConfig(target_list, target_dicts, data, params, 1229 GenerateOutputForConfig(target_list, target_dicts, data, params,
1173 user_config) 1230 user_config)
1174 else: 1231 else:
1175 config_names = target_dicts[target_list[0]]['configurations'].keys() 1232 config_names = target_dicts[target_list[0]]['configurations'].keys()
1176 for config_name in config_names: 1233 for config_name in config_names:
1177 GenerateOutputForConfig(target_list, target_dicts, data, params, 1234 GenerateOutputForConfig(target_list, target_dicts, data, params,
1178 config_name) 1235 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