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 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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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) |
OLD | NEW |