Codebase list gyp / upstream/0.1_svn917
Imported Upstream version 0.1~svn917 Giuseppe Iuculano 13 years ago
111 changed file(s) with 7302 addition(s) and 932 deletion(s). Raw diff Collapse all Expand all
22
33 Google Inc.
44 Steven Knight <knight@baldmt.com>
5 Ryan Norton <rnorton10@gmail.com>
33
44 deps = {
55 "scons":
6 "svn://chrome-svn.corp.google.com/chrome/trunk/src/third_party/scons",
6 "http://src.chromium.org/svn/trunk/src/third_party/scons@44099",
77 }
0 # Copyright 2010, Google Inc.
1 # All rights reserved.
2 #
3 # Redistribution and use in source and binary forms, with or without
4 # modification, are permitted provided that the following conditions are
5 # met:
6 #
7 # * Redistributions of source code must retain the above copyright
8 # notice, this list of conditions and the following disclaimer.
9 # * Redistributions in binary form must reproduce the above
10 # copyright notice, this list of conditions and the following disclaimer
11 # in the documentation and/or other materials provided with the
12 # distribution.
13 # * Neither the name of Google Inc. nor the names of its
14 # contributors may be used to endorse or promote products derived from
15 # this software without specific prior written permission.
16 #
17 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0 # Copyright (c) 2011 The Chromium Authors. All rights reserved.
1 # Use of this source code is governed by a BSD-style license that can be
2 # found in the LICENSE file.
283
294
30 EXCLUDED_PATHS = ()
5 """Top-level presubmit script for GYP.
6
7 See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
8 for more details about the presubmit API built into gcl.
9 """
3110
3211
3312 def CheckChangeOnUpload(input_api, output_api):
3413 report = []
35 black_list = input_api.DEFAULT_BLACK_LIST + EXCLUDED_PATHS
36 sources = lambda x: input_api.FilterSourceFile(x, black_list=black_list)
37 report.extend(input_api.canned_checks.CheckChangeSvnEolStyle(
38 input_api, output_api, sources))
14 report.extend(input_api.canned_checks.PanProjectChecks(
15 input_api, output_api))
3916 return report
4017
4118
4219 def CheckChangeOnCommit(input_api, output_api):
4320 report = []
44 black_list = input_api.DEFAULT_BLACK_LIST + EXCLUDED_PATHS
45 sources = lambda x: input_api.FilterSourceFile(x, black_list=black_list)
46 report.extend(input_api.canned_checks.CheckChangeSvnEolStyle(
47 input_api, output_api, sources))
21 report.extend(input_api.canned_checks.PanProjectChecks(
22 input_api, output_api))
4823 report.extend(input_api.canned_checks.CheckTreeIsOpen(
4924 input_api, output_api,
5025 'http://gyp-status.appspot.com/status',
5126 'http://gyp-status.appspot.com/current'))
5227 return report
28
29
30 def GetPreferredTrySlaves():
31 return ['gyp-win32', 'gyp-win64', 'gyp-linux', 'gyp-mac']
0 #!/usr/bin/python
1 # Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4
5
6 """Argument-less script to select what to run on the buildbots."""
7
8
9 import os
10 import subprocess
11 import sys
12
13
14 def GypTestFormat(title, format, msvs_version=None):
15 """Run the gyp tests for a given format, emitting annotator tags.
16
17 See annotator docs at:
18 https://sites.google.com/a/chromium.org/dev/developers/testing/chromium-build-infrastructure/buildbot-annotations
19 Args:
20 format: gyp format to test.
21 Returns:
22 0 for sucesss, 1 for failure.
23 """
24 print '@@@BUILD_STEP ' + title + '@@@'
25 sys.stdout.flush()
26 buildbot_dir = os.path.dirname(os.path.abspath(__file__))
27 trunk_dir = os.path.dirname(buildbot_dir)
28 root_dir = os.path.dirname(trunk_dir)
29 env = os.environ.copy()
30 if msvs_version:
31 env['GYP_MSVS_VERSION'] = msvs_version
32 retcode = subprocess.call(' '.join(
33 [sys.executable, 'trunk/gyptest.py',
34 '--all',
35 '--passed',
36 '--format', format,
37 '--chdir', 'trunk',
38 '--path', '../scons']),
39 cwd=root_dir, env=env, shell=True)
40 if retcode:
41 # Emit failure tag, and keep going.
42 print '@@@STEP_FAILURE@@@'
43 return 1
44 return 0
45
46
47 def GypBuild():
48 retcode = 0
49 if sys.platform in ['linux', 'linux2']:
50 retcode += GypTestFormat('scons', format='scons')
51 retcode += GypTestFormat('make', format='make')
52 elif sys.platform == 'darwin':
53 retcode += GypTestFormat('xcode', format='xcode')
54 elif sys.platform == 'win32':
55 retcode += GypTestFormat('msvs-2008', format='msvs', msvs_version='2008')
56 if os.environ['BUILDBOT_BUILDERNAME'] == 'gyp-win64':
57 retcode += GypTestFormat('msvs-2010', format='msvs', msvs_version='2010')
58 else:
59 raise Exception('Unknown platform')
60 if retcode:
61 # TODO(bradnelson): once the annotator supports a postscript (section for
62 # after the build proper that could be used for cumulative failures),
63 # use that instead of this. This isolates the final return value so
64 # that it isn't misattributed to the last stage.
65 print '@@@BUILD_STEP failures@@@'
66 sys.exit(retcode)
67
68
69 if __name__ == '__main__':
70 GypBuild()
88 import common
99 import os
1010 import random
11
12 import gyp.common
1113
1214 # hashlib is supplied as of Python 2.5 as the replacement interface for md5
1315 # and other secure hashes. In 2.6, md5 is deprecated. Import hashlib if
104106 """Visual Studio project."""
105107
106108 def __init__(self, path, name = None, dependencies = None, guid = None,
107 config_platform_overrides = None):
109 spec = None, build_file = None, config_platform_overrides = None,
110 fixpath_prefix = None):
108111 """Initializes the project.
109112
110113 Args:
111 path: Relative path to project file.
114 path: Absolute path to the project file.
112115 name: Name of project. If None, the name will be the same as the base
113116 name of the project file.
114117 dependencies: List of other Project objects this project is dependent
115118 upon, if not None.
116119 guid: GUID to use for project, if not None.
120 spec: Dictionary specifying how to build this project.
121 build_file: Filename of the .gyp file that the vcproj file comes from.
117122 config_platform_overrides: optional dict of configuration platforms to
118123 used in place of the default for this target.
124 fixpath_prefix: the path used to adjust the behavior of _fixpath
119125 """
120126 self.path = path
121127 self.guid = guid
122
123 if name:
124 self.name = name
125 else:
126 # Use project filename
127 self.name = os.path.splitext(os.path.basename(path))[0]
128 self.spec = spec
129 self.build_file = build_file
130 # Use project filename if name not specified
131 self.name = name or os.path.splitext(os.path.basename(path))[0]
128132
129133 # Copy passed lists (or set to empty lists)
130134 self.dependencies = list(dependencies or [])
135139 self.config_platform_overrides = config_platform_overrides
136140 else:
137141 self.config_platform_overrides = {}
138
142 self.fixpath_prefix = fixpath_prefix
143
144 def set_dependencies(self, dependencies):
145 self.dependencies = list(dependencies or [])
146
139147 def get_guid(self):
140148 if self.guid is None:
141149 # Set GUID from path
240248 f.write('# %s\r\n' % self.version.Description())
241249
242250 # Project entries
251 sln_root = os.path.split(self.path)[0]
243252 for e in all_entries:
253 relative_path = gyp.common.RelativePath(e.path, sln_root)
244254 f.write('Project("%s") = "%s", "%s", "%s"\r\n' % (
245255 e.entry_type_guid, # Entry type GUID
246256 e.name, # Folder name
247 e.path.replace('/', '\\'), # Folder name (again)
257 relative_path.replace('/', '\\'), # Folder name (again)
248258 e.get_guid(), # Entry GUID
249259 ))
250260
77
88 import common
99 import xml.dom
10 import xml.dom.minidom
11 import MSVSNew
10 import xml_fix
1211
1312 #------------------------------------------------------------------------------
1413
8180 guid: GUID to use for project, if not None.
8281 """
8382 self.name = name
84 self.guid = guid or MSVSNew.MakeGuid(self.project_path)
83 self.guid = guid
8584
8685 # Default to Win32 for platforms.
8786 if not platforms:
237236 def Write(self, writer=common.WriteOnDiff):
238237 """Writes the project file."""
239238 f = writer(self.project_path)
239 fix = xml_fix.XmlFix()
240240 self.doc.writexml(f, encoding='Windows-1252', addindent=' ', newl='\r\n')
241 fix.Cleanup()
241242 f.close()
242243
243244 #------------------------------------------------------------------------------
0 #!/usr/bin/python
1 # Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4
5 """Code to validate and convert settings of the Microsoft build tools.
6
7 This file contains code to validate and convert settings of the Microsoft
8 build tools. The function ConvertToMSBuildSettings(), ValidateMSVSSettings(),
9 and ValidateMSBuildSettings() are the entry points.
10
11 This file was created by comparing the projects created by Visual Studio 2008
12 and Visual Studio 2010 for all available settings through the user interface.
13 The MSBuild schemas were also considered. They are typically found in the
14 MSBuild install directory, e.g. c:\Program Files (x86)\MSBuild
15 """
16
17 import sys
18
19
20 # Dictionaries of settings validators. The key is the tool name, the value is
21 # a dictionary mapping setting names to validation functions.
22 _msvs_validators = {}
23 _msbuild_validators = {}
24
25
26 # A dictionary of settings converters. The key is the tool name, the value is
27 # a dictionary mapping setting names to conversion functions.
28 _msvs_to_msbuild_converters = {}
29
30
31 # Tool name mapping from MSVS to MSBuild.
32 _msbuild_name_of_tool = {}
33
34
35 class _Tool(object):
36 """Represents a tool used by MSVS or MSBuild.
37
38 Attributes:
39 msvs_name: The name of the tool in MSVS.
40 msbuild_name: The name of the tool in MSBuild.
41 """
42
43 def __init__(self, msvs_name, msbuild_name):
44 self.msvs_name = msvs_name
45 self.msbuild_name = msbuild_name
46
47
48 def _AddTool(tool):
49 """Adds a tool to the four dictionaries used to process settings.
50
51 This only defines the tool. Each setting also needs to be added.
52
53 Args:
54 tool: The _Tool object to be added.
55 """
56 _msvs_validators[tool.msvs_name] = {}
57 _msbuild_validators[tool.msbuild_name] = {}
58 _msvs_to_msbuild_converters[tool.msvs_name] = {}
59 _msbuild_name_of_tool[tool.msvs_name] = tool.msbuild_name
60
61
62 def _GetMSBuildToolSettings(msbuild_settings, tool):
63 """Returns an MSBuild tool dictionary. Creates it if needed."""
64 return msbuild_settings.setdefault(tool.msbuild_name, {})
65
66
67 class _Type(object):
68 """Type of settings (Base class)."""
69
70 def ValidateMSVS(self, value):
71 """Verifies that the value is legal for MSVS.
72
73 Args:
74 value: the value to check for this type.
75
76 Raises:
77 ValueError if value is not valid for MSVS.
78 """
79
80 def ValidateMSBuild(self, value):
81 """Verifies that the value is legal for MSBuild.
82
83 Args:
84 value: the value to check for this type.
85
86 Raises:
87 ValueError if value is not valid for MSBuild.
88 """
89
90 def ConvertToMSBuild(self, value):
91 """Returns the MSBuild equivalent of the MSVS value given.
92
93 Args:
94 value: the MSVS value to convert.
95
96 Returns:
97 the MSBuild equivalent.
98
99 Raises:
100 ValueError if value is not valid.
101 """
102 return value
103
104
105 class _String(_Type):
106 """A setting that's just a string."""
107
108 def ValidateMSVS(self, value):
109 if not isinstance(value, basestring):
110 raise ValueError('expected string; got %r' % value)
111
112 def ValidateMSBuild(self, value):
113 if not isinstance(value, basestring):
114 raise ValueError('expected string; got %r' % value)
115
116 def ConvertToMSBuild(self, value):
117 # Convert the macros
118 return ConvertVCMacrosToMSBuild(value)
119
120
121 class _StringList(_Type):
122 """A settings that's a list of strings."""
123
124 def ValidateMSVS(self, value):
125 if not isinstance(value, basestring) and not isinstance(value, list):
126 raise ValueError('expected string list; got %r' % value)
127
128 def ValidateMSBuild(self, value):
129 if not isinstance(value, basestring) and not isinstance(value, list):
130 raise ValueError('expected string list; got %r' % value)
131
132 def ConvertToMSBuild(self, value):
133 # Convert the macros
134 if isinstance(value, list):
135 return [ConvertVCMacrosToMSBuild(i) for i in value]
136 else:
137 return ConvertVCMacrosToMSBuild(value)
138
139
140 class _Boolean(_Type):
141 """Boolean settings, can have the values 'false' or 'true'."""
142
143 def _Validate(self, value):
144 if value != 'true' and value != 'false':
145 raise ValueError('expected bool; got %r' % value)
146
147 def ValidateMSVS(self, value):
148 self._Validate(value)
149
150 def ValidateMSBuild(self, value):
151 self._Validate(value)
152
153 def ConvertToMSBuild(self, value):
154 self._Validate(value)
155 return value
156
157
158 class _Integer(_Type):
159 """Integer settings."""
160
161 def __init__(self, msbuild_base=10):
162 _Type.__init__(self)
163 self._msbuild_base = msbuild_base
164
165 def ValidateMSVS(self, value):
166 # Try to convert, this will raise ValueError if invalid.
167 self.ConvertToMSBuild(value)
168
169 def ValidateMSBuild(self, value):
170 # Try to convert, this will raise ValueError if invalid.
171 int(value, self._msbuild_base)
172
173 def ConvertToMSBuild(self, value):
174 msbuild_format = (self._msbuild_base == 10) and '%d' or '0x%04x'
175 return msbuild_format % int(value)
176
177
178 class _Enumeration(_Type):
179 """Type of settings that is an enumeration.
180
181 In MSVS, the values are indexes like '0', '1', and '2'.
182 MSBuild uses text labels that are more representative, like 'Win32'.
183
184 Constructor args:
185 label_list: an array of MSBuild labels that correspond to the MSVS index.
186 In the rare cases where MSVS has skipped an index value, None is
187 used in the array to indicate the unused spot.
188 new: an array of labels that are new to MSBuild.
189 """
190
191 def __init__(self, label_list, new=None):
192 _Type.__init__(self)
193 self._label_list = label_list
194 self._msbuild_values = set(value for value in label_list
195 if value is not None)
196 if new is not None:
197 self._msbuild_values.update(new)
198
199 def ValidateMSVS(self, value):
200 # Try to convert. It will raise an exception if not valid.
201 self.ConvertToMSBuild(value)
202
203 def ValidateMSBuild(self, value):
204 if value not in self._msbuild_values:
205 raise ValueError('unrecognized enumerated value %s' % value)
206
207 def ConvertToMSBuild(self, value):
208 index = int(value)
209 if index < 0 or index >= len(self._label_list):
210 raise ValueError('index value (%d) not in expected range [0, %d)' %
211 (index, len(self._label_list)))
212 label = self._label_list[index]
213 if label is None:
214 raise ValueError('converted value for %s not specified.' % value)
215 return label
216
217
218 # Instantiate the various generic types.
219 _boolean = _Boolean()
220 _integer = _Integer()
221 # For now, we don't do any special validation on these types:
222 _string = _String()
223 _file_name = _String()
224 _folder_name = _String()
225 _file_list = _StringList()
226 _folder_list = _StringList()
227 _string_list = _StringList()
228 # Some boolean settings went from numerical values to boolean. The
229 # mapping is 0: default, 1: false, 2: true.
230 _newly_boolean = _Enumeration(['', 'false', 'true'])
231
232
233 def _Same(tool, name, setting_type):
234 """Defines a setting that has the same name in MSVS and MSBuild.
235
236 Args:
237 tool: a dictionary that gives the names of the tool for MSVS and MSBuild.
238 name: the name of the setting.
239 setting_type: the type of this setting.
240 """
241 _Renamed(tool, name, name, setting_type)
242
243
244 def _Renamed(tool, msvs_name, msbuild_name, setting_type):
245 """Defines a setting for which the name has changed.
246
247 Args:
248 tool: a dictionary that gives the names of the tool for MSVS and MSBuild.
249 msvs_name: the name of the MSVS setting.
250 msbuild_name: the name of the MSBuild setting.
251 setting_type: the type of this setting.
252 """
253
254 def _Translate(value, msbuild_settings):
255 msbuild_tool_settings = _GetMSBuildToolSettings(msbuild_settings, tool)
256 msbuild_tool_settings[msbuild_name] = setting_type.ConvertToMSBuild(value)
257
258 _msvs_validators[tool.msvs_name][msvs_name] = setting_type.ValidateMSVS
259 _msbuild_validators[tool.msbuild_name][msbuild_name] = (
260 setting_type.ValidateMSBuild)
261 _msvs_to_msbuild_converters[tool.msvs_name][msvs_name] = _Translate
262
263
264 def _Moved(tool, settings_name, msbuild_tool_name, setting_type):
265 _MovedAndRenamed(tool, settings_name, msbuild_tool_name, settings_name,
266 setting_type)
267
268
269 def _MovedAndRenamed(tool, msvs_settings_name, msbuild_tool_name,
270 msbuild_settings_name, setting_type):
271 """Defines a setting that may have moved to a new section.
272
273 Args:
274 tool: a dictionary that gives the names of the tool for MSVS and MSBuild.
275 msvs_settings_name: the MSVS name of the setting.
276 msbuild_tool_name: the name of the MSBuild tool to place the setting under.
277 msbuild_settings_name: the MSBuild name of the setting.
278 setting_type: the type of this setting.
279 """
280
281 def _Translate(value, msbuild_settings):
282 tool_settings = msbuild_settings.setdefault(msbuild_tool_name, {})
283 tool_settings[msbuild_settings_name] = setting_type.ConvertToMSBuild(value)
284
285 _msvs_validators[tool.msvs_name][msvs_settings_name] = (
286 setting_type.ValidateMSVS)
287 validator = setting_type.ValidateMSBuild
288 _msbuild_validators[msbuild_tool_name][msbuild_settings_name] = validator
289 _msvs_to_msbuild_converters[tool.msvs_name][msvs_settings_name] = _Translate
290
291
292 def _MSVSOnly(tool, name, setting_type):
293 """Defines a setting that is only found in MSVS.
294
295 Args:
296 tool: a dictionary that gives the names of the tool for MSVS and MSBuild.
297 name: the name of the setting.
298 setting_type: the type of this setting.
299 """
300
301 def _Translate(unused_value, unused_msbuild_settings):
302 # Since this is for MSVS only settings, no translation will happen.
303 pass
304
305 _msvs_validators[tool.msvs_name][name] = setting_type.ValidateMSVS
306 _msvs_to_msbuild_converters[tool.msvs_name][name] = _Translate
307
308
309 def _MSBuildOnly(tool, name, setting_type):
310 """Defines a setting that is only found in MSBuild.
311
312 Args:
313 tool: a dictionary that gives the names of the tool for MSVS and MSBuild.
314 name: the name of the setting.
315 setting_type: the type of this setting.
316 """
317 _msbuild_validators[tool.msbuild_name][name] = setting_type.ValidateMSBuild
318
319
320 def _ConvertedToAdditionalOption(tool, msvs_name, flag):
321 """Defines a setting that's handled via a command line option in MSBuild.
322
323 Args:
324 tool: a dictionary that gives the names of the tool for MSVS and MSBuild.
325 msvs_name: the name of the MSVS setting that if 'true' becomes a flag
326 flag: the flag to insert at the end of the AdditionalOptions
327 """
328
329 def _Translate(value, msbuild_settings):
330 if value == 'true':
331 tool_settings = _GetMSBuildToolSettings(msbuild_settings, tool)
332 if 'AdditionalOptions' in tool_settings:
333 new_flags = '%s %s' % (tool_settings['AdditionalOptions'], flag)
334 else:
335 new_flags = flag
336 tool_settings['AdditionalOptions'] = new_flags
337 _msvs_validators[tool.msvs_name][msvs_name] = _boolean.ValidateMSVS
338 _msvs_to_msbuild_converters[tool.msvs_name][msvs_name] = _Translate
339
340
341 def _CustomGeneratePreprocessedFile(tool, msvs_name):
342 def _Translate(value, msbuild_settings):
343 tool_settings = _GetMSBuildToolSettings(msbuild_settings, tool)
344 if value == '0':
345 tool_settings['PreprocessToFile'] = 'false'
346 tool_settings['PreprocessSuppressLineNumbers'] = 'false'
347 elif value == '1': # /P
348 tool_settings['PreprocessToFile'] = 'true'
349 tool_settings['PreprocessSuppressLineNumbers'] = 'false'
350 elif value == '2': # /EP /P
351 tool_settings['PreprocessToFile'] = 'true'
352 tool_settings['PreprocessSuppressLineNumbers'] = 'true'
353 else:
354 raise ValueError('value must be one of [0, 1, 2]; got %s' % value)
355 # Create a bogus validator that looks for '0', '1', or '2'
356 msvs_validator = _Enumeration(['a', 'b', 'c']).ValidateMSVS
357 _msvs_validators[tool.msvs_name][msvs_name] = msvs_validator
358 msbuild_validator = _boolean.ValidateMSBuild
359 msbuild_tool_validators = _msbuild_validators[tool.msbuild_name]
360 msbuild_tool_validators['PreprocessToFile'] = msbuild_validator
361 msbuild_tool_validators['PreprocessSuppressLineNumbers'] = msbuild_validator
362 _msvs_to_msbuild_converters[tool.msvs_name][msvs_name] = _Translate
363
364
365 def ConvertVCMacrosToMSBuild(s):
366 """Convert the the MSVS macros found in the string to the MSBuild equivalent.
367
368 This list is probably not exhaustive. Add as needed.
369 """
370 if '$' in s:
371 replace_map = {
372 '$(ConfigurationName)': '$(Configuration)',
373 '$(InputDir)': '%(RootDir)%(Directory)',
374 '$(InputExt)': '%(Extension)',
375 '$(InputFileName)': '%(Filename)%(Extension)',
376 '$(InputName)': '%(Filename)',
377 '$(InputPath)': '%(FullPath)',
378 '$(ParentName)': '$(ProjectFileName)',
379 '$(PlatformName)': '$(Platform)',
380 '$(SafeInputName)': '%(Filename)',
381
382 '$(IntDir)\\': '$(IntDir)',
383 '$(OutDir)\\': '$(OutDir)',
384 '$(IntDir)/': '$(IntDir)',
385 '$(OutDir)/': '$(OutDir)',
386 }
387 for old, new in replace_map.iteritems():
388 s = s.replace(old, new)
389 return s
390
391
392 def ConvertToMSBuildSettings(msvs_settings, stderr=sys.stderr):
393 """Converts MSVS settings (VS2008 and earlier) to MSBuild settings (VS2010+).
394
395 Args:
396 msvs_settings: A dictionary. The key is the tool name. The values are
397 themselves dictionaries of settings and their values.
398 stderr: The stream receiving the error messages.
399
400 Returns:
401 A dictionary of MSBuild settings. The key is either the MSBuild tool name
402 or the empty string (for the global settings). The values are themselves
403 dictionaries of settings and their values.
404 """
405 msbuild_settings = {}
406 for msvs_tool_name, msvs_tool_settings in msvs_settings.iteritems():
407 if msvs_tool_name in _msvs_to_msbuild_converters:
408 msvs_tool = _msvs_to_msbuild_converters[msvs_tool_name]
409 for msvs_setting, msvs_value in msvs_tool_settings.iteritems():
410 if msvs_setting in msvs_tool:
411 # Invoke the translation function.
412 try:
413 msvs_tool[msvs_setting](msvs_value, msbuild_settings)
414 except ValueError, e:
415 print >> stderr, ('Warning: while converting %s/%s to MSBuild, '
416 '%s' % (msvs_tool_name, msvs_setting, e))
417 else:
418 # We don't know this setting. Give a warning.
419 print >> stderr, ('Warning: unrecognized setting %s/%s '
420 'while converting to MSBuild.' %
421 (msvs_tool_name, msvs_setting))
422 else:
423 print >> stderr, ('Warning: unrecognized tool %s while converting to '
424 'MSBuild.' % msvs_tool_name)
425 return msbuild_settings
426
427
428 def ValidateMSVSSettings(settings, stderr=sys.stderr):
429 """Validates that the names of the settings are valid for MSVS.
430
431 Args:
432 settings: A dictionary. The key is the tool name. The values are
433 themselves dictionaries of settings and their values.
434 stderr: The stream receiving the error messages.
435 """
436 _ValidateSettings(_msvs_validators, settings, stderr)
437
438
439 def ValidateMSBuildSettings(settings, stderr=sys.stderr):
440 """Validates that the names of the settings are valid for MSBuild.
441
442 Args:
443 settings: A dictionary. The key is the tool name. The values are
444 themselves dictionaries of settings and their values.
445 stderr: The stream receiving the error messages.
446 """
447 _ValidateSettings(_msbuild_validators, settings, stderr)
448
449
450 def _ValidateSettings(validators, settings, stderr):
451 """Validates that the settings are valid for MSBuild or MSVS.
452
453 We currently only validate the names of the settings, not their values.
454
455 Args:
456 validators: A dictionary of tools and their validators.
457 settings: A dictionary. The key is the tool name. The values are
458 themselves dictionaries of settings and their values.
459 stderr: The stream receiving the error messages.
460 """
461 for tool_name in settings:
462 if tool_name in validators:
463 tool_validators = validators[tool_name]
464 for setting, value in settings[tool_name].iteritems():
465 if setting in tool_validators:
466 try:
467 tool_validators[setting](value)
468 except ValueError, e:
469 print >> stderr, ('Warning: for %s/%s, %s' %
470 (tool_name, setting, e))
471 else:
472 print >> stderr, ('Warning: unrecognized setting %s/%s' %
473 (tool_name, setting))
474 else:
475 print >> stderr, ('Warning: unrecognized tool %s' % tool_name)
476
477
478 # MSVS and MBuild names of the tools.
479 _compile = _Tool('VCCLCompilerTool', 'ClCompile')
480 _link = _Tool('VCLinkerTool', 'Link')
481 _midl = _Tool('VCMIDLTool', 'Midl')
482 _rc = _Tool('VCResourceCompilerTool', 'ResourceCompile')
483 _lib = _Tool('VCLibrarianTool', 'Lib')
484 _manifest = _Tool('VCManifestTool', 'Mt')
485
486
487 _AddTool(_compile)
488 _AddTool(_link)
489 _AddTool(_midl)
490 _AddTool(_rc)
491 _AddTool(_lib)
492 _AddTool(_manifest)
493 # Add sections only found in the MSBuild settings.
494 _msbuild_validators[''] = {}
495 _msbuild_validators['ProjectReference'] = {}
496 _msbuild_validators['ManifestResourceCompile'] = {}
497
498 # Descriptions of the compiler options, i.e. VCCLCompilerTool in MSVS and
499 # ClCompile in MSBuild.
500 # See "c:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\1033\cl.xml" for
501 # the schema of the MSBuild ClCompile settings.
502
503 # Options that have the same name in MSVS and MSBuild
504 _Same(_compile, 'AdditionalIncludeDirectories', _folder_list) # /I
505 _Same(_compile, 'AdditionalOptions', _string_list)
506 _Same(_compile, 'AdditionalUsingDirectories', _folder_list) # /AI
507 _Same(_compile, 'AssemblerListingLocation', _file_name) # /Fa
508 _Same(_compile, 'BrowseInformationFile', _file_name)
509 _Same(_compile, 'BufferSecurityCheck', _boolean) # /GS
510 _Same(_compile, 'DisableLanguageExtensions', _boolean) # /Za
511 _Same(_compile, 'DisableSpecificWarnings', _string_list) # /wd
512 _Same(_compile, 'EnableFiberSafeOptimizations', _boolean) # /GT
513 _Same(_compile, 'EnablePREfast', _boolean) # /analyze Visible='false'
514 _Same(_compile, 'ExpandAttributedSource', _boolean) # /Fx
515 _Same(_compile, 'FloatingPointExceptions', _boolean) # /fp:except
516 _Same(_compile, 'ForceConformanceInForLoopScope', _boolean) # /Zc:forScope
517 _Same(_compile, 'ForcedIncludeFiles', _file_list) # /FI
518 _Same(_compile, 'ForcedUsingFiles', _file_list) # /FU
519 _Same(_compile, 'GenerateXMLDocumentationFiles', _boolean) # /doc
520 _Same(_compile, 'IgnoreStandardIncludePath', _boolean) # /X
521 _Same(_compile, 'MinimalRebuild', _boolean) # /Gm
522 _Same(_compile, 'OmitDefaultLibName', _boolean) # /Zl
523 _Same(_compile, 'OmitFramePointers', _boolean) # /Oy
524 _Same(_compile, 'PreprocessorDefinitions', _string_list) # /D
525 _Same(_compile, 'ProgramDataBaseFileName', _file_name) # /Fd
526 _Same(_compile, 'RuntimeTypeInfo', _boolean) # /GR
527 _Same(_compile, 'ShowIncludes', _boolean) # /showIncludes
528 _Same(_compile, 'SmallerTypeCheck', _boolean) # /RTCc
529 _Same(_compile, 'StringPooling', _boolean) # /GF
530 _Same(_compile, 'SuppressStartupBanner', _boolean) # /nologo
531 _Same(_compile, 'TreatWChar_tAsBuiltInType', _boolean) # /Zc:wchar_t
532 _Same(_compile, 'UndefineAllPreprocessorDefinitions', _boolean) # /u
533 _Same(_compile, 'UndefinePreprocessorDefinitions', _string_list) # /U
534 _Same(_compile, 'UseFullPaths', _boolean) # /FC
535 _Same(_compile, 'WholeProgramOptimization', _boolean) # /GL
536 _Same(_compile, 'XMLDocumentationFileName', _file_name)
537
538 _Same(_compile, 'AssemblerOutput',
539 _Enumeration(['NoListing',
540 'AssemblyCode', # /FA
541 'All', # /FAcs
542 'AssemblyAndMachineCode', # /FAc
543 'AssemblyAndSourceCode'])) # /FAs
544 _Same(_compile, 'BasicRuntimeChecks',
545 _Enumeration(['Default',
546 'StackFrameRuntimeCheck', # /RTCs
547 'UninitializedLocalUsageCheck', # /RTCu
548 'EnableFastChecks'])) # /RTC1
549 _Same(_compile, 'BrowseInformation',
550 _Enumeration(['false',
551 'true', # /FR
552 'true'])) # /Fr
553 _Same(_compile, 'CallingConvention',
554 _Enumeration(['Cdecl', # /Gd
555 'FastCall', # /Gr
556 'StdCall'])) # /Gz
557 _Same(_compile, 'CompileAs',
558 _Enumeration(['Default',
559 'CompileAsC', # /TC
560 'CompileAsCpp'])) # /TP
561 _Same(_compile, 'DebugInformationFormat',
562 _Enumeration(['', # Disabled
563 'OldStyle', # /Z7
564 None,
565 'ProgramDatabase', # /Zi
566 'EditAndContinue'])) # /ZI
567 _Same(_compile, 'EnableEnhancedInstructionSet',
568 _Enumeration(['NotSet',
569 'StreamingSIMDExtensions', # /arch:SSE
570 'StreamingSIMDExtensions2'])) # /arch:SSE2
571 _Same(_compile, 'ErrorReporting',
572 _Enumeration(['None', # /errorReport:none
573 'Prompt', # /errorReport:prompt
574 'Queue'], # /errorReport:queue
575 new=['Send'])) # /errorReport:send"
576 _Same(_compile, 'ExceptionHandling',
577 _Enumeration(['false',
578 'Sync', # /EHsc
579 'Async'], # /EHa
580 new=['SyncCThrow'])) # /EHs
581 _Same(_compile, 'FavorSizeOrSpeed',
582 _Enumeration(['Neither',
583 'Speed', # /Ot
584 'Size'])) # /Os
585 _Same(_compile, 'FloatingPointModel',
586 _Enumeration(['Precise', # /fp:precise
587 'Strict', # /fp:strict
588 'Fast'])) # /fp:fast
589 _Same(_compile, 'InlineFunctionExpansion',
590 _Enumeration(['Default',
591 'OnlyExplicitInline', # /Ob1
592 'AnySuitable'], # /Ob2
593 new=['Disabled'])) # /Ob0
594 _Same(_compile, 'Optimization',
595 _Enumeration(['Disabled', # /Od
596 'MinSpace', # /O1
597 'MaxSpeed', # /O2
598 'Full'])) # /Ox
599 _Same(_compile, 'RuntimeLibrary',
600 _Enumeration(['MultiThreaded', # /MT
601 'MultiThreadedDebug', # /MTd
602 'MultiThreadedDLL', # /MD
603 'MultiThreadedDebugDLL'])) # /MDd
604 _Same(_compile, 'StructMemberAlignment',
605 _Enumeration(['Default',
606 '1Byte', # /Zp1
607 '2Bytes', # /Zp2
608 '4Bytes', # /Zp4
609 '8Bytes', # /Zp8
610 '16Bytes'])) # /Zp16
611 _Same(_compile, 'WarningLevel',
612 _Enumeration(['TurnOffAllWarnings', # /W0
613 'Level1', # /W1
614 'Level2', # /W2
615 'Level3', # /W3
616 'Level4'], # /W4
617 new=['EnableAllWarnings'])) # /Wall
618
619 # Options found in MSVS that have been renamed in MSBuild.
620 _Renamed(_compile, 'EnableFunctionLevelLinking', 'FunctionLevelLinking',
621 _boolean) # /Gy
622 _Renamed(_compile, 'EnableIntrinsicFunctions', 'IntrinsicFunctions',
623 _boolean) # /Oi
624 _Renamed(_compile, 'KeepComments', 'PreprocessKeepComments', _boolean) # /C
625 _Renamed(_compile, 'ObjectFile', 'ObjectFileName', _file_name) # /Fo
626 _Renamed(_compile, 'OpenMP', 'OpenMPSupport', _boolean) # /openmp
627 _Renamed(_compile, 'PrecompiledHeaderThrough', 'PrecompiledHeaderFile',
628 _file_name) # Used with /Yc and /Yu
629 _Renamed(_compile, 'PrecompiledHeaderFile', 'PrecompiledHeaderOutputFile',
630 _file_name) # /Fp
631 _Renamed(_compile, 'UsePrecompiledHeader', 'PrecompiledHeader',
632 _Enumeration(['NotUsing', # VS recognized '' for this value too.
633 'Create', # /Yc
634 'Use'])) # /Yu
635 _Renamed(_compile, 'WarnAsError', 'TreatWarningAsError', _boolean) # /WX
636
637 _ConvertedToAdditionalOption(_compile, 'DefaultCharIsUnsigned', '/J')
638
639 # MSVS options not found in MSBuild.
640 _MSVSOnly(_compile, 'Detect64BitPortabilityProblems', _boolean)
641 _MSVSOnly(_compile, 'UseUnicodeResponseFiles', _boolean)
642
643 # MSBuild options not found in MSVS.
644 _MSBuildOnly(_compile, 'BuildingInIDE', _boolean)
645 _MSBuildOnly(_compile, 'CompileAsManaged',
646 _Enumeration([], new=['false',
647 'true', # /clr
648 'Pure', # /clr:pure
649 'Safe', # /clr:safe
650 'OldSyntax'])) # /clr:oldSyntax
651 _MSBuildOnly(_compile, 'CreateHotpatchableImage', _boolean) # /hotpatch
652 _MSBuildOnly(_compile, 'MultiProcessorCompilation', _boolean) # /MP
653 _MSBuildOnly(_compile, 'PreprocessOutputPath', _string) # /Fi
654 _MSBuildOnly(_compile, 'ProcessorNumber', _integer) # the number of processors
655 _MSBuildOnly(_compile, 'TrackerLogDirectory', _folder_name)
656 _MSBuildOnly(_compile, 'TreatSpecificWarningsAsErrors', _string_list) # /we
657 _MSBuildOnly(_compile, 'UseUnicodeForAssemblerListing', _boolean) # /FAu
658
659 # Defines a setting that needs very customized processing
660 _CustomGeneratePreprocessedFile(_compile, 'GeneratePreprocessedFile')
661
662
663 # Directives for converting MSVS VCLinkerTool to MSBuild Link.
664 # See "c:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\1033\link.xml" for
665 # the schema of the MSBuild Link settings.
666
667 # Options that have the same name in MSVS and MSBuild
668 _Same(_link, 'AdditionalDependencies', _file_list)
669 _Same(_link, 'AdditionalLibraryDirectories', _folder_list) # /LIBPATH
670 # /MANIFESTDEPENDENCY:
671 _Same(_link, 'AdditionalManifestDependencies', _file_list)
672 _Same(_link, 'AdditionalOptions', _string_list)
673 _Same(_link, 'AddModuleNamesToAssembly', _file_list) # /ASSEMBLYMODULE
674 _Same(_link, 'AllowIsolation', _boolean) # /ALLOWISOLATION
675 _Same(_link, 'AssemblyLinkResource', _file_list) # /ASSEMBLYLINKRESOURCE
676 _Same(_link, 'BaseAddress', _string) # /BASE
677 _Same(_link, 'CLRUnmanagedCodeCheck', _boolean) # /CLRUNMANAGEDCODECHECK
678 _Same(_link, 'DelayLoadDLLs', _file_list) # /DELAYLOAD
679 _Same(_link, 'DelaySign', _boolean) # /DELAYSIGN
680 _Same(_link, 'EmbedManagedResourceFile', _file_list) # /ASSEMBLYRESOURCE
681 _Same(_link, 'EnableUAC', _boolean) # /MANIFESTUAC
682 _Same(_link, 'EntryPointSymbol', _string) # /ENTRY
683 _Same(_link, 'ForceSymbolReferences', _file_list) # /INCLUDE
684 _Same(_link, 'FunctionOrder', _file_name) # /ORDER
685 _Same(_link, 'GenerateDebugInformation', _boolean) # /DEBUG
686 _Same(_link, 'GenerateMapFile', _boolean) # /MAP
687 _Same(_link, 'HeapCommitSize', _string)
688 _Same(_link, 'HeapReserveSize', _string) # /HEAP
689 _Same(_link, 'IgnoreAllDefaultLibraries', _boolean) # /NODEFAULTLIB
690 _Same(_link, 'IgnoreEmbeddedIDL', _boolean) # /IGNOREIDL
691 _Same(_link, 'ImportLibrary', _file_name) # /IMPLIB
692 _Same(_link, 'KeyContainer', _file_name) # /KEYCONTAINER
693 _Same(_link, 'KeyFile', _file_name) # /KEYFILE
694 _Same(_link, 'ManifestFile', _file_name) # /ManifestFile
695 _Same(_link, 'MapExports', _boolean) # /MAPINFO:EXPORTS
696 _Same(_link, 'MapFileName', _file_name)
697 _Same(_link, 'MergedIDLBaseFileName', _file_name) # /IDLOUT
698 _Same(_link, 'MergeSections', _string) # /MERGE
699 _Same(_link, 'MidlCommandFile', _file_name) # /MIDL
700 _Same(_link, 'ModuleDefinitionFile', _file_name) # /DEF
701 _Same(_link, 'OutputFile', _file_name) # /OUT
702 _Same(_link, 'PerUserRedirection', _boolean)
703 _Same(_link, 'Profile', _boolean) # /PROFILE
704 _Same(_link, 'ProfileGuidedDatabase', _file_name) # /PGD
705 _Same(_link, 'ProgramDatabaseFile', _file_name) # /PDB
706 _Same(_link, 'RegisterOutput', _boolean)
707 _Same(_link, 'SetChecksum', _boolean) # /RELEASE
708 _Same(_link, 'StackCommitSize', _string)
709 _Same(_link, 'StackReserveSize', _string) # /STACK
710 _Same(_link, 'StripPrivateSymbols', _file_name) # /PDBSTRIPPED
711 _Same(_link, 'SupportUnloadOfDelayLoadedDLL', _boolean) # /DELAY:UNLOAD
712 _Same(_link, 'SuppressStartupBanner', _boolean) # /NOLOGO
713 _Same(_link, 'SwapRunFromCD', _boolean) # /SWAPRUN:CD
714 _Same(_link, 'TurnOffAssemblyGeneration', _boolean) # /NOASSEMBLY
715 _Same(_link, 'TypeLibraryFile', _file_name) # /TLBOUT
716 _Same(_link, 'TypeLibraryResourceID', _integer) # /TLBID
717 _Same(_link, 'UACUIAccess', _boolean) # /uiAccess='true'
718 _Same(_link, 'Version', _string) # /VERSION
719
720 _Same(_link, 'EnableCOMDATFolding', _newly_boolean) # /OPT:ICF
721 _Same(_link, 'FixedBaseAddress', _newly_boolean) # /FIXED
722 _Same(_link, 'LargeAddressAware', _newly_boolean) # /LARGEADDRESSAWARE
723 _Same(_link, 'OptimizeReferences', _newly_boolean) # /OPT:REF
724 _Same(_link, 'RandomizedBaseAddress', _newly_boolean) # /DYNAMICBASE
725 _Same(_link, 'TerminalServerAware', _newly_boolean) # /TSAWARE
726
727 _subsystem_enumeration = _Enumeration(
728 ['NotSet',
729 'Console', # /SUBSYSTEM:CONSOLE
730 'Windows', # /SUBSYSTEM:WINDOWS
731 'Native', # /SUBSYSTEM:NATIVE
732 'EFI Application', # /SUBSYSTEM:EFI_APPLICATION
733 'EFI Boot Service Driver', # /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER
734 'EFI ROM', # /SUBSYSTEM:EFI_ROM
735 'EFI Runtime', # /SUBSYSTEM:EFI_RUNTIME_DRIVER
736 'WindowsCE'], # /SUBSYSTEM:WINDOWSCE
737 new=['POSIX']) # /SUBSYSTEM:POSIX
738
739 _target_machine_enumeration = _Enumeration(
740 ['NotSet',
741 'MachineX86', # /MACHINE:X86
742 None,
743 'MachineARM', # /MACHINE:ARM
744 'MachineEBC', # /MACHINE:EBC
745 'MachineIA64', # /MACHINE:IA64
746 None,
747 'MachineMIPS', # /MACHINE:MIPS
748 'MachineMIPS16', # /MACHINE:MIPS16
749 'MachineMIPSFPU', # /MACHINE:MIPSFPU
750 'MachineMIPSFPU16', # /MACHINE:MIPSFPU16
751 None,
752 None,
753 None,
754 'MachineSH4', # /MACHINE:SH4
755 None,
756 'MachineTHUMB', # /MACHINE:THUMB
757 'MachineX64']) # /MACHINE:X64
758
759 _Same(_link, 'AssemblyDebug',
760 _Enumeration(['',
761 'true', # /ASSEMBLYDEBUG
762 'false'])) # /ASSEMBLYDEBUG:DISABLE
763 _Same(_link, 'CLRImageType',
764 _Enumeration(['Default',
765 'ForceIJWImage', # /CLRIMAGETYPE:IJW
766 'ForcePureILImage', # /Switch="CLRIMAGETYPE:PURE
767 'ForceSafeILImage'])) # /Switch="CLRIMAGETYPE:SAFE
768 _Same(_link, 'CLRThreadAttribute',
769 _Enumeration(['DefaultThreadingAttribute', # /CLRTHREADATTRIBUTE:NONE
770 'MTAThreadingAttribute', # /CLRTHREADATTRIBUTE:MTA
771 'STAThreadingAttribute'])) # /CLRTHREADATTRIBUTE:STA
772 _Same(_link, 'DataExecutionPrevention',
773 _Enumeration(['',
774 'false', # /NXCOMPAT:NO
775 'true'])) # /NXCOMPAT
776 _Same(_link, 'Driver',
777 _Enumeration(['NotSet',
778 'Driver', # /Driver
779 'UpOnly', # /DRIVER:UPONLY
780 'WDM'])) # /DRIVER:WDM
781 _Same(_link, 'LinkTimeCodeGeneration',
782 _Enumeration(['Default',
783 'UseLinkTimeCodeGeneration', # /LTCG
784 'PGInstrument', # /LTCG:PGInstrument
785 'PGOptimization', # /LTCG:PGOptimize
786 'PGUpdate'])) # /LTCG:PGUpdate
787 _Same(_link, 'ShowProgress',
788 _Enumeration(['NotSet',
789 'LinkVerbose', # /VERBOSE
790 'LinkVerboseLib'], # /VERBOSE:Lib
791 new=['LinkVerboseICF', # /VERBOSE:ICF
792 'LinkVerboseREF', # /VERBOSE:REF
793 'LinkVerboseSAFESEH', # /VERBOSE:SAFESEH
794 'LinkVerboseCLR'])) # /VERBOSE:CLR
795 _Same(_link, 'SubSystem', _subsystem_enumeration)
796 _Same(_link, 'TargetMachine', _target_machine_enumeration)
797 _Same(_link, 'UACExecutionLevel',
798 _Enumeration(['AsInvoker', # /level='asInvoker'
799 'HighestAvailable', # /level='highestAvailable'
800 'RequireAdministrator'])) # /level='requireAdministrator'
801
802
803 # Options found in MSVS that have been renamed in MSBuild.
804 _Renamed(_link, 'ErrorReporting', 'LinkErrorReporting',
805 _Enumeration(['NoErrorReport', # /ERRORREPORT:NONE
806 'PromptImmediately', # /ERRORREPORT:PROMPT
807 'QueueForNextLogin'], # /ERRORREPORT:QUEUE
808 new=['SendErrorReport'])) # /ERRORREPORT:SEND
809 _Renamed(_link, 'IgnoreDefaultLibraryNames', 'IgnoreSpecificDefaultLibraries',
810 _file_list) # /NODEFAULTLIB
811 _Renamed(_link, 'ResourceOnlyDLL', 'NoEntryPoint', _boolean) # /NOENTRY
812 _Renamed(_link, 'SwapRunFromNet', 'SwapRunFromNET', _boolean) # /SWAPRUN:NET
813
814 _Moved(_link, 'GenerateManifest', '', _boolean)
815 _Moved(_link, 'IgnoreImportLibrary', '', _boolean)
816 _Moved(_link, 'LinkIncremental', '', _newly_boolean)
817 _Moved(_link, 'LinkLibraryDependencies', 'ProjectReference', _boolean)
818 _Moved(_link, 'UseLibraryDependencyInputs', 'ProjectReference', _boolean)
819
820 # MSVS options not found in MSBuild.
821 _MSVSOnly(_link, 'OptimizeForWindows98', _newly_boolean)
822 _MSVSOnly(_link, 'UseUnicodeResponseFiles', _boolean)
823 # TODO(jeanluc) I don't think these are genuine settings but byproducts of Gyp.
824 _MSVSOnly(_link, 'AdditionalLibraryDirectories_excluded', _folder_list)
825
826 # MSBuild options not found in MSVS.
827 _MSBuildOnly(_link, 'BuildingInIDE', _boolean)
828 _MSBuildOnly(_link, 'ImageHasSafeExceptionHandlers', _boolean) # /SAFESEH
829 _MSBuildOnly(_link, 'LinkDLL', _boolean) # /DLL Visible='false'
830 _MSBuildOnly(_link, 'LinkStatus', _boolean) # /LTCG:STATUS
831 _MSBuildOnly(_link, 'PreventDllBinding', _boolean) # /ALLOWBIND
832 _MSBuildOnly(_link, 'SupportNobindOfDelayLoadedDLL', _boolean) # /DELAY:NOBIND
833 _MSBuildOnly(_link, 'TrackerLogDirectory', _folder_name)
834 _MSBuildOnly(_link, 'TreatLinkerWarningAsErrors', _boolean) # /WX
835 _MSBuildOnly(_link, 'MinimumRequiredVersion', _string)
836 _MSBuildOnly(_link, 'MSDOSStubFileName', _file_name) # /STUB Visible='false'
837 _MSBuildOnly(_link, 'SectionAlignment', _integer) # /ALIGN
838 _MSBuildOnly(_link, 'SpecifySectionAttributes', _string) # /SECTION
839 _MSBuildOnly(_link, 'ForceFileOutput',
840 _Enumeration([], new=['Enabled', # /FORCE
841 # /FORCE:MULTIPLE
842 'MultiplyDefinedSymbolOnly',
843 'UndefinedSymbolOnly'])) # /FORCE:UNRESOLVED
844 _MSBuildOnly(_link, 'CreateHotPatchableImage',
845 _Enumeration([], new=['Enabled', # /FUNCTIONPADMIN
846 'X86Image', # /FUNCTIONPADMIN:5
847 'X64Image', # /FUNCTIONPADMIN:6
848 'ItaniumImage'])) # /FUNCTIONPADMIN:16
849 _MSBuildOnly(_link, 'CLRSupportLastError',
850 _Enumeration([], new=['Enabled', # /CLRSupportLastError
851 'Disabled', # /CLRSupportLastError:NO
852 # /CLRSupportLastError:SYSTEMDLL
853 'SystemDlls']))
854
855
856 # Directives for converting VCResourceCompilerTool to ResourceCompile.
857 # See "c:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\1033\rc.xml" for
858 # the schema of the MSBuild ResourceCompile settings.
859
860 _Same(_rc, 'AdditionalOptions', _string_list)
861 _Same(_rc, 'AdditionalIncludeDirectories', _folder_list) # /I
862 _Same(_rc, 'Culture', _Integer(msbuild_base=16))
863 _Same(_rc, 'IgnoreStandardIncludePath', _boolean) # /X
864 _Same(_rc, 'PreprocessorDefinitions', _string_list) # /D
865 _Same(_rc, 'ResourceOutputFileName', _string) # /fo
866 _Same(_rc, 'ShowProgress', _boolean) # /v
867 # There is no UI in VisualStudio 2008 to set the following properties.
868 # However they are found in CL and other tools. Include them here for
869 # completeness, as they are very likely to have the same usage pattern.
870 _Same(_rc, 'SuppressStartupBanner', _boolean) # /nologo
871 _Same(_rc, 'UndefinePreprocessorDefinitions', _string_list) # /u
872
873 # MSBuild options not found in MSVS.
874 _MSBuildOnly(_rc, 'NullTerminateStrings', _boolean) # /n
875 _MSBuildOnly(_rc, 'TrackerLogDirectory', _folder_name)
876
877
878 # Directives for converting VCMIDLTool to Midl.
879 # See "c:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\1033\midl.xml" for
880 # the schema of the MSBuild Midl settings.
881
882 _Same(_midl, 'AdditionalIncludeDirectories', _folder_list) # /I
883 _Same(_midl, 'AdditionalOptions', _string_list)
884 _Same(_midl, 'CPreprocessOptions', _string) # /cpp_opt
885 _Same(_midl, 'ErrorCheckAllocations', _boolean) # /error allocation
886 _Same(_midl, 'ErrorCheckBounds', _boolean) # /error bounds_check
887 _Same(_midl, 'ErrorCheckEnumRange', _boolean) # /error enum
888 _Same(_midl, 'ErrorCheckRefPointers', _boolean) # /error ref
889 _Same(_midl, 'ErrorCheckStubData', _boolean) # /error stub_data
890 _Same(_midl, 'GenerateStublessProxies', _boolean) # /Oicf
891 _Same(_midl, 'GenerateTypeLibrary', _boolean)
892 _Same(_midl, 'HeaderFileName', _file_name) # /h
893 _Same(_midl, 'IgnoreStandardIncludePath', _boolean) # /no_def_idir
894 _Same(_midl, 'InterfaceIdentifierFileName', _file_name) # /iid
895 _Same(_midl, 'MkTypLibCompatible', _boolean) # /mktyplib203
896 _Same(_midl, 'OutputDirectory', _string) # /out
897 _Same(_midl, 'PreprocessorDefinitions', _string_list) # /D
898 _Same(_midl, 'ProxyFileName', _file_name) # /proxy
899 _Same(_midl, 'RedirectOutputAndErrors', _file_name) # /o
900 _Same(_midl, 'SuppressStartupBanner', _boolean) # /nologo
901 _Same(_midl, 'TypeLibraryName', _file_name) # /tlb
902 _Same(_midl, 'UndefinePreprocessorDefinitions', _string_list) # /U
903 _Same(_midl, 'WarnAsError', _boolean) # /WX
904
905 _Same(_midl, 'DefaultCharType',
906 _Enumeration(['Unsigned', # /char unsigned
907 'Signed', # /char signed
908 'Ascii'])) # /char ascii7
909 _Same(_midl, 'TargetEnvironment',
910 _Enumeration(['NotSet',
911 'Win32', # /env win32
912 'Itanium', # /env ia64
913 'X64'])) # /env x64
914 _Same(_midl, 'EnableErrorChecks',
915 _Enumeration(['EnableCustom',
916 'None', # /error none
917 'All'])) # /error all
918 _Same(_midl, 'StructMemberAlignment',
919 _Enumeration(['NotSet',
920 '1', # Zp1
921 '2', # Zp2
922 '4', # Zp4
923 '8'])) # Zp8
924 _Same(_midl, 'WarningLevel',
925 _Enumeration(['0', # /W0
926 '1', # /W1
927 '2', # /W2
928 '3', # /W3
929 '4'])) # /W4
930
931 _Renamed(_midl, 'DLLDataFileName', 'DllDataFileName', _file_name) # /dlldata
932 _Renamed(_midl, 'ValidateParameters', 'ValidateAllParameters',
933 _boolean) # /robust
934
935 # MSBuild options not found in MSVS.
936 _MSBuildOnly(_midl, 'ApplicationConfigurationMode', _boolean) # /app_config
937 _MSBuildOnly(_midl, 'ClientStubFile', _file_name) # /cstub
938 _MSBuildOnly(_midl, 'GenerateClientFiles',
939 _Enumeration([], new=['Stub', # /client stub
940 'None'])) # /client none
941 _MSBuildOnly(_midl, 'GenerateServerFiles',
942 _Enumeration([], new=['Stub', # /client stub
943 'None'])) # /client none
944 _MSBuildOnly(_midl, 'LocaleID', _integer) # /lcid DECIMAL
945 _MSBuildOnly(_midl, 'ServerStubFile', _file_name) # /sstub
946 _MSBuildOnly(_midl, 'SuppressCompilerWarnings', _boolean) # /no_warn
947 _MSBuildOnly(_midl, 'TrackerLogDirectory', _folder_name)
948 _MSBuildOnly(_midl, 'TypeLibFormat',
949 _Enumeration([], new=['NewFormat', # /newtlb
950 'OldFormat'])) # /oldtlb
951
952
953 # Directives for converting VCLibrarianTool to Lib.
954 # See "c:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\1033\lib.xml" for
955 # the schema of the MSBuild Lib settings.
956
957 _Same(_lib, 'AdditionalDependencies', _file_list)
958 _Same(_lib, 'AdditionalLibraryDirectories', _folder_list) # /LIBPATH
959 _Same(_lib, 'AdditionalOptions', _string_list)
960 _Same(_lib, 'ExportNamedFunctions', _string_list) # /EXPORT
961 _Same(_lib, 'ForceSymbolReferences', _string) # /INCLUDE
962 _Same(_lib, 'IgnoreAllDefaultLibraries', _boolean) # /NODEFAULTLIB
963 _Same(_lib, 'IgnoreSpecificDefaultLibraries', _file_list) # /NODEFAULTLIB
964 _Same(_lib, 'ModuleDefinitionFile', _file_name) # /DEF
965 _Same(_lib, 'OutputFile', _file_name) # /OUT
966 _Same(_lib, 'SuppressStartupBanner', _boolean) # /NOLOGO
967 _Same(_lib, 'UseUnicodeResponseFiles', _boolean)
968
969 # TODO(jeanluc) _link defines the same value that gets moved to
970 # ProjectReference. We may want to validate that they are consistent.
971 _Moved(_lib, 'LinkLibraryDependencies', 'ProjectReference', _boolean)
972
973 # TODO(jeanluc) I don't think these are genuine settings but byproducts of Gyp.
974 _MSVSOnly(_lib, 'AdditionalLibraryDirectories_excluded', _folder_list)
975
976 _MSBuildOnly(_lib, 'DisplayLibrary', _string) # /LIST Visible='false'
977 _MSBuildOnly(_lib, 'ErrorReporting',
978 _Enumeration([], new=['PromptImmediately', # /ERRORREPORT:PROMPT
979 'QueueForNextLogin', # /ERRORREPORT:QUEUE
980 'SendErrorReport', # /ERRORREPORT:SEND
981 'NoErrorReport'])) # /ERRORREPORT:NONE
982 _MSBuildOnly(_lib, 'LinkTimeCodeGeneration', _boolean) # /LTCG
983 _MSBuildOnly(_lib, 'MinimumRequiredVersion', _string)
984 _MSBuildOnly(_lib, 'Name', _file_name) # /NAME
985 _MSBuildOnly(_lib, 'RemoveObjects', _file_list) # /REMOVE
986 _MSBuildOnly(_lib, 'SubSystem', _subsystem_enumeration)
987 _MSBuildOnly(_lib, 'TargetMachine', _target_machine_enumeration)
988 _MSBuildOnly(_lib, 'TrackerLogDirectory', _folder_name)
989 _MSBuildOnly(_lib, 'TreatLibWarningAsErrors', _boolean) # /WX
990 _MSBuildOnly(_lib, 'Verbose', _boolean)
991
992
993 # Directives for converting VCManifestTool to Mt.
994 # See "c:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\1033\mt.xml" for
995 # the schema of the MSBuild Lib settings.
996
997 # Options that have the same name in MSVS and MSBuild
998 _Same(_manifest, 'AdditionalManifestFiles', _file_list) # /manifest
999 _Same(_manifest, 'AdditionalOptions', _string_list)
1000 _Same(_manifest, 'AssemblyIdentity', _string) # /identity:
1001 _Same(_manifest, 'ComponentFileName', _file_name) # /dll
1002 _Same(_manifest, 'GenerateCatalogFiles', _boolean) # /makecdfs
1003 _Same(_manifest, 'InputResourceManifests', _string) # /inputresource
1004 _Same(_manifest, 'OutputManifestFile', _file_name) # /out
1005 _Same(_manifest, 'RegistrarScriptFile', _file_name) # /rgs
1006 _Same(_manifest, 'ReplacementsFile', _file_name) # /replacements
1007 _Same(_manifest, 'SuppressStartupBanner', _boolean) # /nologo
1008 _Same(_manifest, 'TypeLibraryFile', _file_name) # /tlb:
1009 _Same(_manifest, 'UpdateFileHashes', _boolean) # /hashupdate
1010 _Same(_manifest, 'UpdateFileHashesSearchPath', _file_name)
1011 _Same(_manifest, 'VerboseOutput', _boolean) # /verbose
1012
1013 # Options that have moved location.
1014 _MovedAndRenamed(_manifest, 'ManifestResourceFile',
1015 'ManifestResourceCompile',
1016 'ResourceOutputFileName',
1017 _file_name)
1018 _Moved(_manifest, 'EmbedManifest', '', _boolean)
1019
1020 # MSVS options not found in MSBuild.
1021 _MSVSOnly(_manifest, 'DependencyInformationFile', _file_name)
1022 _MSVSOnly(_manifest, 'UseFAT32Workaround', _boolean)
1023 _MSVSOnly(_manifest, 'UseUnicodeResponseFiles', _boolean)
1024
1025 # MSBuild options not found in MSVS.
1026 _MSBuildOnly(_manifest, 'EnableDPIAwareness', _boolean)
1027 _MSBuildOnly(_manifest, 'GenerateCategoryTags', _boolean) # /category
1028 _MSBuildOnly(_manifest, 'ManifestFromManagedAssembly',
1029 _file_name) # /managedassemblyname
1030 _MSBuildOnly(_manifest, 'OutputResourceManifests', _string) # /outputresource
1031 _MSBuildOnly(_manifest, 'SuppressDependencyElement', _boolean) # /nodependency
1032 _MSBuildOnly(_manifest, 'TrackerLogDirectory', _folder_name)
0 #!/usr/bin/python
1
2 # Copyright (c) 2011 Google Inc. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 """Unit tests for the MSVSSettings.py file."""
7
8 import StringIO
9 import unittest
10 import MSVSSettings
11
12
13 class TestSequenceFunctions(unittest.TestCase):
14
15 def setUp(self):
16 self.stderr = StringIO.StringIO()
17
18 def _ExpectedWarnings(self, expected):
19 """Compares recorded lines to expected warnings."""
20 self.stderr.seek(0)
21 actual = self.stderr.read().split('\n')
22 actual = [line for line in actual if line]
23 self.assertEqual(sorted(expected), sorted(actual))
24
25 def testValidateMSVSSettings_tool_names(self):
26 """Tests that only MSVS tool names are allowed."""
27 MSVSSettings.ValidateMSVSSettings(
28 {'VCCLCompilerTool': {},
29 'VCLinkerTool': {},
30 'VCMIDLTool': {},
31 'foo': {},
32 'VCResourceCompilerTool': {},
33 'VCLibrarianTool': {},
34 'VCManifestTool': {},
35 'ClCompile': {}},
36 self.stderr)
37 self._ExpectedWarnings([
38 'Warning: unrecognized tool foo',
39 'Warning: unrecognized tool ClCompile'])
40
41 def testValidateMSVSSettings_settings(self):
42 """Tests that for invalid MSVS settings."""
43 MSVSSettings.ValidateMSVSSettings(
44 {'VCCLCompilerTool': {
45 'AdditionalIncludeDirectories': 'folder1;folder2',
46 'AdditionalOptions': ['string1', 'string2'],
47 'AdditionalUsingDirectories': 'folder1;folder2',
48 'AssemblerListingLocation': 'a_file_name',
49 'AssemblerOutput': '0',
50 'BasicRuntimeChecks': '5',
51 'BrowseInformation': 'fdkslj',
52 'BrowseInformationFile': 'a_file_name',
53 'BufferSecurityCheck': 'true',
54 'CallingConvention': '-1',
55 'CompileAs': '1',
56 'DebugInformationFormat': '2',
57 'DefaultCharIsUnsigned': 'true',
58 'Detect64BitPortabilityProblems': 'true',
59 'DisableLanguageExtensions': 'true',
60 'DisableSpecificWarnings': 'string1;string2',
61 'EnableEnhancedInstructionSet': '1',
62 'EnableFiberSafeOptimizations': 'true',
63 'EnableFunctionLevelLinking': 'true',
64 'EnableIntrinsicFunctions': 'true',
65 'EnablePREfast': 'true',
66 'Enableprefast': 'bogus',
67 'ErrorReporting': '1',
68 'ExceptionHandling': '1',
69 'ExpandAttributedSource': 'true',
70 'FavorSizeOrSpeed': '1',
71 'FloatingPointExceptions': 'true',
72 'FloatingPointModel': '1',
73 'ForceConformanceInForLoopScope': 'true',
74 'ForcedIncludeFiles': 'file1;file2',
75 'ForcedUsingFiles': 'file1;file2',
76 'GeneratePreprocessedFile': '1',
77 'GenerateXMLDocumentationFiles': 'true',
78 'IgnoreStandardIncludePath': 'true',
79 'InlineFunctionExpansion': '1',
80 'KeepComments': 'true',
81 'MinimalRebuild': 'true',
82 'ObjectFile': 'a_file_name',
83 'OmitDefaultLibName': 'true',
84 'OmitFramePointers': 'true',
85 'OpenMP': 'true',
86 'Optimization': '1',
87 'PrecompiledHeaderFile': 'a_file_name',
88 'PrecompiledHeaderThrough': 'a_file_name',
89 'PreprocessorDefinitions': 'string1;string2',
90 'ProgramDataBaseFileName': 'a_file_name',
91 'RuntimeLibrary': '1',
92 'RuntimeTypeInfo': 'true',
93 'ShowIncludes': 'true',
94 'SmallerTypeCheck': 'true',
95 'StringPooling': 'true',
96 'StructMemberAlignment': '1',
97 'SuppressStartupBanner': 'true',
98 'TreatWChar_tAsBuiltInType': 'true',
99 'UndefineAllPreprocessorDefinitions': 'true',
100 'UndefinePreprocessorDefinitions': 'string1;string2',
101 'UseFullPaths': 'true',
102 'UsePrecompiledHeader': '1',
103 'UseUnicodeResponseFiles': 'true',
104 'WarnAsError': 'true',
105 'WarningLevel': '1',
106 'WholeProgramOptimization': 'true',
107 'XMLDocumentationFileName': 'a_file_name',
108 'ZZXYZ': 'bogus'},
109 'VCLinkerTool': {
110 'AdditionalDependencies': 'file1;file2',
111 'AdditionalLibraryDirectories': 'folder1;folder2',
112 'AdditionalManifestDependencies': 'file1;file2',
113 'AdditionalOptions': 'a string1',
114 'AddModuleNamesToAssembly': 'file1;file2',
115 'AllowIsolation': 'true',
116 'AssemblyDebug': '2',
117 'AssemblyLinkResource': 'file1;file2',
118 'BaseAddress': 'a string1',
119 'CLRImageType': '2',
120 'CLRThreadAttribute': '2',
121 'CLRUnmanagedCodeCheck': 'true',
122 'DataExecutionPrevention': '2',
123 'DelayLoadDLLs': 'file1;file2',
124 'DelaySign': 'true',
125 'Driver': '2',
126 'EmbedManagedResourceFile': 'file1;file2',
127 'EnableCOMDATFolding': '2',
128 'EnableUAC': 'true',
129 'EntryPointSymbol': 'a string1',
130 'ErrorReporting': '2',
131 'FixedBaseAddress': '2',
132 'ForceSymbolReferences': 'file1;file2',
133 'FunctionOrder': 'a_file_name',
134 'GenerateDebugInformation': 'true',
135 'GenerateManifest': 'true',
136 'GenerateMapFile': 'true',
137 'HeapCommitSize': 'a string1',
138 'HeapReserveSize': 'a string1',
139 'IgnoreAllDefaultLibraries': 'true',
140 'IgnoreDefaultLibraryNames': 'file1;file2',
141 'IgnoreEmbeddedIDL': 'true',
142 'IgnoreImportLibrary': 'true',
143 'ImportLibrary': 'a_file_name',
144 'KeyContainer': 'a_file_name',
145 'KeyFile': 'a_file_name',
146 'LargeAddressAware': '2',
147 'LinkIncremental': '2',
148 'LinkLibraryDependencies': 'true',
149 'LinkTimeCodeGeneration': '2',
150 'ManifestFile': 'a_file_name',
151 'MapExports': 'true',
152 'MapFileName': 'a_file_name',
153 'MergedIDLBaseFileName': 'a_file_name',
154 'MergeSections': 'a string1',
155 'MidlCommandFile': 'a_file_name',
156 'ModuleDefinitionFile': 'a_file_name',
157 'OptimizeForWindows98': '1',
158 'OptimizeReferences': '2',
159 'OutputFile': 'a_file_name',
160 'PerUserRedirection': 'true',
161 'Profile': 'true',
162 'ProfileGuidedDatabase': 'a_file_name',
163 'ProgramDatabaseFile': 'a_file_name',
164 'RandomizedBaseAddress': '2',
165 'RegisterOutput': 'true',
166 'ResourceOnlyDLL': 'true',
167 'SetChecksum': 'true',
168 'ShowProgress': '2',
169 'StackCommitSize': 'a string1',
170 'StackReserveSize': 'a string1',
171 'StripPrivateSymbols': 'a_file_name',
172 'SubSystem': '2',
173 'SupportUnloadOfDelayLoadedDLL': 'true',
174 'SuppressStartupBanner': 'true',
175 'SwapRunFromCD': 'true',
176 'SwapRunFromNet': 'true',
177 'TargetMachine': '2',
178 'TerminalServerAware': '2',
179 'TurnOffAssemblyGeneration': 'true',
180 'TypeLibraryFile': 'a_file_name',
181 'TypeLibraryResourceID': '33',
182 'UACExecutionLevel': '2',
183 'UACUIAccess': 'true',
184 'UseLibraryDependencyInputs': 'true',
185 'UseUnicodeResponseFiles': 'true',
186 'Version': 'a string1'},
187 'VCMIDLTool': {
188 'AdditionalIncludeDirectories': 'folder1;folder2',
189 'AdditionalOptions': 'a string1',
190 'CPreprocessOptions': 'a string1',
191 'DefaultCharType': '1',
192 'DLLDataFileName': 'a_file_name',
193 'EnableErrorChecks': '1',
194 'ErrorCheckAllocations': 'true',
195 'ErrorCheckBounds': 'true',
196 'ErrorCheckEnumRange': 'true',
197 'ErrorCheckRefPointers': 'true',
198 'ErrorCheckStubData': 'true',
199 'GenerateStublessProxies': 'true',
200 'GenerateTypeLibrary': 'true',
201 'HeaderFileName': 'a_file_name',
202 'IgnoreStandardIncludePath': 'true',
203 'InterfaceIdentifierFileName': 'a_file_name',
204 'MkTypLibCompatible': 'true',
205 'notgood': 'bogus',
206 'OutputDirectory': 'a string1',
207 'PreprocessorDefinitions': 'string1;string2',
208 'ProxyFileName': 'a_file_name',
209 'RedirectOutputAndErrors': 'a_file_name',
210 'StructMemberAlignment': '1',
211 'SuppressStartupBanner': 'true',
212 'TargetEnvironment': '1',
213 'TypeLibraryName': 'a_file_name',
214 'UndefinePreprocessorDefinitions': 'string1;string2',
215 'ValidateParameters': 'true',
216 'WarnAsError': 'true',
217 'WarningLevel': '1'},
218 'VCResourceCompilerTool': {
219 'AdditionalOptions': 'a string1',
220 'AdditionalIncludeDirectories': 'folder1;folder2',
221 'Culture': '1003',
222 'IgnoreStandardIncludePath': 'true',
223 'notgood2': 'bogus',
224 'PreprocessorDefinitions': 'string1;string2',
225 'ResourceOutputFileName': 'a string1',
226 'ShowProgress': 'true',
227 'SuppressStartupBanner': 'true',
228 'UndefinePreprocessorDefinitions': 'string1;string2'},
229 'VCLibrarianTool': {
230 'AdditionalDependencies': 'file1;file2',
231 'AdditionalLibraryDirectories': 'folder1;folder2',
232 'AdditionalOptions': 'a string1',
233 'ExportNamedFunctions': 'string1;string2',
234 'ForceSymbolReferences': 'a string1',
235 'IgnoreAllDefaultLibraries': 'true',
236 'IgnoreSpecificDefaultLibraries': 'file1;file2',
237 'LinkLibraryDependencies': 'true',
238 'ModuleDefinitionFile': 'a_file_name',
239 'OutputFile': 'a_file_name',
240 'SuppressStartupBanner': 'true',
241 'UseUnicodeResponseFiles': 'true'},
242 'VCManifestTool': {
243 'AdditionalManifestFiles': 'file1;file2',
244 'AdditionalOptions': 'a string1',
245 'AssemblyIdentity': 'a string1',
246 'ComponentFileName': 'a_file_name',
247 'DependencyInformationFile': 'a_file_name',
248 'GenerateCatalogFiles': 'true',
249 'InputResourceManifests': 'a string1',
250 'ManifestResourceFile': 'a_file_name',
251 'OutputManifestFile': 'a_file_name',
252 'RegistrarScriptFile': 'a_file_name',
253 'ReplacementsFile': 'a_file_name',
254 'SuppressStartupBanner': 'true',
255 'TypeLibraryFile': 'a_file_name',
256 'UpdateFileHashes': 'truel',
257 'UpdateFileHashesSearchPath': 'a_file_name',
258 'UseFAT32Workaround': 'true',
259 'UseUnicodeResponseFiles': 'true',
260 'VerboseOutput': 'true'}},
261 self.stderr)
262 self._ExpectedWarnings([
263 'Warning: for VCCLCompilerTool/BasicRuntimeChecks, '
264 'index value (5) not in expected range [0, 4)',
265 'Warning: for VCCLCompilerTool/BrowseInformation, '
266 "invalid literal for int() with base 10: 'fdkslj'",
267 'Warning: for VCCLCompilerTool/CallingConvention, '
268 'index value (-1) not in expected range [0, 3)',
269 'Warning: for VCCLCompilerTool/DebugInformationFormat, '
270 'converted value for 2 not specified.',
271 'Warning: unrecognized setting VCCLCompilerTool/Enableprefast',
272 'Warning: unrecognized setting VCCLCompilerTool/ZZXYZ',
273 'Warning: for VCLinkerTool/TargetMachine, '
274 'converted value for 2 not specified.',
275 'Warning: unrecognized setting VCMIDLTool/notgood',
276 'Warning: unrecognized setting VCResourceCompilerTool/notgood2',
277 'Warning: for VCManifestTool/UpdateFileHashes, '
278 "expected bool; got 'truel'"
279 ''])
280
281 def testValidateMSBuildSettings_settings(self):
282 """Tests that for invalid MSBuild settings."""
283 MSVSSettings.ValidateMSBuildSettings(
284 {'ClCompile': {
285 'AdditionalIncludeDirectories': 'folder1;folder2',
286 'AdditionalOptions': ['string1', 'string2'],
287 'AdditionalUsingDirectories': 'folder1;folder2',
288 'AssemblerListingLocation': 'a_file_name',
289 'AssemblerOutput': 'NoListing',
290 'BasicRuntimeChecks': 'StackFrameRuntimeCheck',
291 'BrowseInformation': 'false',
292 'BrowseInformationFile': 'a_file_name',
293 'BufferSecurityCheck': 'true',
294 'BuildingInIDE': 'true',
295 'CallingConvention': 'Cdecl',
296 'CompileAs': 'CompileAsC',
297 'CompileAsManaged': 'Pure',
298 'CreateHotpatchableImage': 'true',
299 'DebugInformationFormat': 'ProgramDatabase',
300 'DisableLanguageExtensions': 'true',
301 'DisableSpecificWarnings': 'string1;string2',
302 'EnableEnhancedInstructionSet': 'StreamingSIMDExtensions',
303 'EnableFiberSafeOptimizations': 'true',
304 'EnablePREfast': 'true',
305 'Enableprefast': 'bogus',
306 'ErrorReporting': 'Prompt',
307 'ExceptionHandling': 'SyncCThrow',
308 'ExpandAttributedSource': 'true',
309 'FavorSizeOrSpeed': 'Neither',
310 'FloatingPointExceptions': 'true',
311 'FloatingPointModel': 'Precise',
312 'ForceConformanceInForLoopScope': 'true',
313 'ForcedIncludeFiles': 'file1;file2',
314 'ForcedUsingFiles': 'file1;file2',
315 'FunctionLevelLinking': 'false',
316 'GenerateXMLDocumentationFiles': 'true',
317 'IgnoreStandardIncludePath': 'true',
318 'InlineFunctionExpansion': 'OnlyExplicitInline',
319 'IntrinsicFunctions': 'false',
320 'MinimalRebuild': 'true',
321 'MultiProcessorCompilation': 'true',
322 'ObjectFileName': 'a_file_name',
323 'OmitDefaultLibName': 'true',
324 'OmitFramePointers': 'true',
325 'OpenMPSupport': 'true',
326 'Optimization': 'Disabled',
327 'PrecompiledHeader': 'NotUsing',
328 'PrecompiledHeaderFile': 'a_file_name',
329 'PrecompiledHeaderOutputFile': 'a_file_name',
330 'PreprocessKeepComments': 'true',
331 'PreprocessorDefinitions': 'string1;string2',
332 'PreprocessOutputPath': 'a string1',
333 'PreprocessSuppressLineNumbers': 'false',
334 'PreprocessToFile': 'false',
335 'ProcessorNumber': '33',
336 'ProgramDataBaseFileName': 'a_file_name',
337 'RuntimeLibrary': 'MultiThreaded',
338 'RuntimeTypeInfo': 'true',
339 'ShowIncludes': 'true',
340 'SmallerTypeCheck': 'true',
341 'StringPooling': 'true',
342 'StructMemberAlignment': '1Byte',
343 'SuppressStartupBanner': 'true',
344 'TrackerLogDirectory': 'a_folder',
345 'TreatSpecificWarningsAsErrors': 'string1;string2',
346 'TreatWarningAsError': 'true',
347 'TreatWChar_tAsBuiltInType': 'true',
348 'UndefineAllPreprocessorDefinitions': 'true',
349 'UndefinePreprocessorDefinitions': 'string1;string2',
350 'UseFullPaths': 'true',
351 'UseUnicodeForAssemblerListing': 'true',
352 'WarningLevel': 'TurnOffAllWarnings',
353 'WholeProgramOptimization': 'true',
354 'XMLDocumentationFileName': 'a_file_name',
355 'ZZXYZ': 'bogus'},
356 'Link': {
357 'AdditionalDependencies': 'file1;file2',
358 'AdditionalLibraryDirectories': 'folder1;folder2',
359 'AdditionalManifestDependencies': 'file1;file2',
360 'AdditionalOptions': 'a string1',
361 'AddModuleNamesToAssembly': 'file1;file2',
362 'AllowIsolation': 'true',
363 'AssemblyDebug': '',
364 'AssemblyLinkResource': 'file1;file2',
365 'BaseAddress': 'a string1',
366 'BuildingInIDE': 'true',
367 'CLRImageType': 'ForceIJWImage',
368 'CLRSupportLastError': 'Enabled',
369 'CLRThreadAttribute': 'MTAThreadingAttribute',
370 'CLRUnmanagedCodeCheck': 'true',
371 'CreateHotPatchableImage': 'X86Image',
372 'DataExecutionPrevention': 'false',
373 'DelayLoadDLLs': 'file1;file2',
374 'DelaySign': 'true',
375 'Driver': 'NotSet',
376 'EmbedManagedResourceFile': 'file1;file2',
377 'EnableCOMDATFolding': 'false',
378 'EnableUAC': 'true',
379 'EntryPointSymbol': 'a string1',
380 'FixedBaseAddress': 'false',
381 'ForceFileOutput': 'Enabled',
382 'ForceSymbolReferences': 'file1;file2',
383 'FunctionOrder': 'a_file_name',
384 'GenerateDebugInformation': 'true',
385 'GenerateMapFile': 'true',
386 'HeapCommitSize': 'a string1',
387 'HeapReserveSize': 'a string1',
388 'IgnoreAllDefaultLibraries': 'true',
389 'IgnoreEmbeddedIDL': 'true',
390 'IgnoreSpecificDefaultLibraries': 'a_file_list',
391 'ImageHasSafeExceptionHandlers': 'true',
392 'ImportLibrary': 'a_file_name',
393 'KeyContainer': 'a_file_name',
394 'KeyFile': 'a_file_name',
395 'LargeAddressAware': 'false',
396 'LinkDLL': 'true',
397 'LinkErrorReporting': 'SendErrorReport',
398 'LinkStatus': 'true',
399 'LinkTimeCodeGeneration': 'UseLinkTimeCodeGeneration',
400 'ManifestFile': 'a_file_name',
401 'MapExports': 'true',
402 'MapFileName': 'a_file_name',
403 'MergedIDLBaseFileName': 'a_file_name',
404 'MergeSections': 'a string1',
405 'MidlCommandFile': 'a_file_name',
406 'MinimumRequiredVersion': 'a string1',
407 'ModuleDefinitionFile': 'a_file_name',
408 'MSDOSStubFileName': 'a_file_name',
409 'NoEntryPoint': 'true',
410 'OptimizeReferences': 'false',
411 'OutputFile': 'a_file_name',
412 'PerUserRedirection': 'true',
413 'PreventDllBinding': 'true',
414 'Profile': 'true',
415 'ProfileGuidedDatabase': 'a_file_name',
416 'ProgramDatabaseFile': 'a_file_name',
417 'RandomizedBaseAddress': 'false',
418 'RegisterOutput': 'true',
419 'SectionAlignment': '33',
420 'SetChecksum': 'true',
421 'ShowProgress': 'LinkVerboseREF',
422 'SpecifySectionAttributes': 'a string1',
423 'StackCommitSize': 'a string1',
424 'StackReserveSize': 'a string1',
425 'StripPrivateSymbols': 'a_file_name',
426 'SubSystem': 'Console',
427 'SupportNobindOfDelayLoadedDLL': 'true',
428 'SupportUnloadOfDelayLoadedDLL': 'true',
429 'SuppressStartupBanner': 'true',
430 'SwapRunFromCD': 'true',
431 'SwapRunFromNET': 'true',
432 'TargetMachine': 'MachineX86',
433 'TerminalServerAware': 'false',
434 'TrackerLogDirectory': 'a_folder',
435 'TreatLinkerWarningAsErrors': 'true',
436 'TurnOffAssemblyGeneration': 'true',
437 'TypeLibraryFile': 'a_file_name',
438 'TypeLibraryResourceID': '33',
439 'UACExecutionLevel': 'AsInvoker',
440 'UACUIAccess': 'true',
441 'Version': 'a string1'},
442 'ResourceCompile': {
443 'AdditionalIncludeDirectories': 'folder1;folder2',
444 'AdditionalOptions': 'a string1',
445 'Culture': '0x236',
446 'IgnoreStandardIncludePath': 'true',
447 'NullTerminateStrings': 'true',
448 'PreprocessorDefinitions': 'string1;string2',
449 'ResourceOutputFileName': 'a string1',
450 'ShowProgress': 'true',
451 'SuppressStartupBanner': 'true',
452 'TrackerLogDirectory': 'a_folder',
453 'UndefinePreprocessorDefinitions': 'string1;string2'},
454 'Midl': {
455 'AdditionalIncludeDirectories': 'folder1;folder2',
456 'AdditionalOptions': 'a string1',
457 'ApplicationConfigurationMode': 'true',
458 'ClientStubFile': 'a_file_name',
459 'CPreprocessOptions': 'a string1',
460 'DefaultCharType': 'Signed',
461 'DllDataFileName': 'a_file_name',
462 'EnableErrorChecks': 'EnableCustom',
463 'ErrorCheckAllocations': 'true',
464 'ErrorCheckBounds': 'true',
465 'ErrorCheckEnumRange': 'true',
466 'ErrorCheckRefPointers': 'true',
467 'ErrorCheckStubData': 'true',
468 'GenerateClientFiles': 'Stub',
469 'GenerateServerFiles': 'None',
470 'GenerateStublessProxies': 'true',
471 'GenerateTypeLibrary': 'true',
472 'HeaderFileName': 'a_file_name',
473 'IgnoreStandardIncludePath': 'true',
474 'InterfaceIdentifierFileName': 'a_file_name',
475 'LocaleID': '33',
476 'MkTypLibCompatible': 'true',
477 'OutputDirectory': 'a string1',
478 'PreprocessorDefinitions': 'string1;string2',
479 'ProxyFileName': 'a_file_name',
480 'RedirectOutputAndErrors': 'a_file_name',
481 'ServerStubFile': 'a_file_name',
482 'StructMemberAlignment': 'NotSet',
483 'SuppressCompilerWarnings': 'true',
484 'SuppressStartupBanner': 'true',
485 'TargetEnvironment': 'Itanium',
486 'TrackerLogDirectory': 'a_folder',
487 'TypeLibFormat': 'NewFormat',
488 'TypeLibraryName': 'a_file_name',
489 'UndefinePreprocessorDefinitions': 'string1;string2',
490 'ValidateAllParameters': 'true',
491 'WarnAsError': 'true',
492 'WarningLevel': '1'},
493 'Lib': {
494 'AdditionalDependencies': 'file1;file2',
495 'AdditionalLibraryDirectories': 'folder1;folder2',
496 'AdditionalOptions': 'a string1',
497 'DisplayLibrary': 'a string1',
498 'ErrorReporting': 'PromptImmediately',
499 'ExportNamedFunctions': 'string1;string2',
500 'ForceSymbolReferences': 'a string1',
501 'IgnoreAllDefaultLibraries': 'true',
502 'IgnoreSpecificDefaultLibraries': 'file1;file2',
503 'LinkTimeCodeGeneration': 'true',
504 'MinimumRequiredVersion': 'a string1',
505 'ModuleDefinitionFile': 'a_file_name',
506 'Name': 'a_file_name',
507 'OutputFile': 'a_file_name',
508 'RemoveObjects': 'file1;file2',
509 'SubSystem': 'Console',
510 'SuppressStartupBanner': 'true',
511 'TargetMachine': 'MachineX86i',
512 'TrackerLogDirectory': 'a_folder',
513 'TreatLibWarningAsErrors': 'true',
514 'UseUnicodeResponseFiles': 'true',
515 'Verbose': 'true'},
516 'Mt': {
517 'AdditionalManifestFiles': 'file1;file2',
518 'AdditionalOptions': 'a string1',
519 'AssemblyIdentity': 'a string1',
520 'ComponentFileName': 'a_file_name',
521 'EnableDPIAwareness': 'fal',
522 'GenerateCatalogFiles': 'truel',
523 'GenerateCategoryTags': 'true',
524 'InputResourceManifests': 'a string1',
525 'ManifestFromManagedAssembly': 'a_file_name',
526 'notgood3': 'bogus',
527 'OutputManifestFile': 'a_file_name',
528 'OutputResourceManifests': 'a string1',
529 'RegistrarScriptFile': 'a_file_name',
530 'ReplacementsFile': 'a_file_name',
531 'SuppressDependencyElement': 'true',
532 'SuppressStartupBanner': 'true',
533 'TrackerLogDirectory': 'a_folder',
534 'TypeLibraryFile': 'a_file_name',
535 'UpdateFileHashes': 'true',
536 'UpdateFileHashesSearchPath': 'a_file_name',
537 'VerboseOutput': 'true'},
538 'ProjectReference': {
539 'LinkLibraryDependencies': 'true',
540 'UseLibraryDependencyInputs': 'true'},
541 'ManifestResourceCompile': {
542 'ResourceOutputFileName': 'a_file_name'},
543 '': {
544 'EmbedManifest': 'true',
545 'GenerateManifest': 'true',
546 'IgnoreImportLibrary': 'true',
547 'LinkIncremental': 'false'}},
548 self.stderr)
549 self._ExpectedWarnings([
550 'Warning: unrecognized setting ClCompile/Enableprefast',
551 'Warning: unrecognized setting ClCompile/ZZXYZ',
552 'Warning: unrecognized setting Mt/notgood3',
553 "Warning: for Mt/GenerateCatalogFiles, expected bool; got 'truel'",
554 'Warning: for Lib/TargetMachine, unrecognized enumerated value '
555 'MachineX86i',
556 "Warning: for Mt/EnableDPIAwareness, expected bool; got 'fal'"])
557
558 def testConvertToMSBuildSettings_empty(self):
559 """Tests an empty conversion."""
560 msvs_settings = {}
561 expected_msbuild_settings = {}
562 actual_msbuild_settings = MSVSSettings.ConvertToMSBuildSettings(
563 msvs_settings,
564 self.stderr)
565 self.assertEqual(expected_msbuild_settings, actual_msbuild_settings)
566 self._ExpectedWarnings([])
567
568 def testConvertToMSBuildSettings_minimal(self):
569 """Tests a minimal conversion."""
570 msvs_settings = {
571 'VCCLCompilerTool': {
572 'AdditionalIncludeDirectories': 'dir1',
573 'AdditionalOptions': '/foo',
574 'BasicRuntimeChecks': '0',
575 },
576 'VCLinkerTool': {
577 'LinkTimeCodeGeneration': '1',
578 'ErrorReporting': '1',
579 'DataExecutionPrevention': '2',
580 },
581 }
582 expected_msbuild_settings = {
583 'ClCompile': {
584 'AdditionalIncludeDirectories': 'dir1',
585 'AdditionalOptions': '/foo',
586 'BasicRuntimeChecks': 'Default',
587 },
588 'Link': {
589 'LinkTimeCodeGeneration': 'UseLinkTimeCodeGeneration',
590 'LinkErrorReporting': 'PromptImmediately',
591 'DataExecutionPrevention': 'true',
592 },
593 }
594 actual_msbuild_settings = MSVSSettings.ConvertToMSBuildSettings(
595 msvs_settings,
596 self.stderr)
597 self.assertEqual(expected_msbuild_settings, actual_msbuild_settings)
598 self._ExpectedWarnings([])
599
600 def testConvertToMSBuildSettings_warnings(self):
601 """Tests conversion that generates warnings."""
602 msvs_settings = {
603 'VCCLCompilerTool': {
604 'AdditionalIncludeDirectories': '1',
605 'AdditionalOptions': '2',
606 # These are incorrect values:
607 'BasicRuntimeChecks': '12',
608 'BrowseInformation': '21',
609 'UsePrecompiledHeader': '13',
610 'GeneratePreprocessedFile': '14'},
611 'VCLinkerTool': {
612 # These are incorrect values:
613 'Driver': '10',
614 'LinkTimeCodeGeneration': '31',
615 'ErrorReporting': '21',
616 'FixedBaseAddress': '6'},
617 'VCResourceCompilerTool': {
618 # Custom
619 'Culture': '1003'}}
620 expected_msbuild_settings = {
621 'ClCompile': {
622 'AdditionalIncludeDirectories': '1',
623 'AdditionalOptions': '2'},
624 'Link': {},
625 'ResourceCompile': {
626 # Custom
627 'Culture': '0x03eb'}}
628 actual_msbuild_settings = MSVSSettings.ConvertToMSBuildSettings(
629 msvs_settings,
630 self.stderr)
631 self.assertEqual(expected_msbuild_settings, actual_msbuild_settings)
632 self._ExpectedWarnings([
633 'Warning: while converting VCCLCompilerTool/BasicRuntimeChecks to '
634 'MSBuild, index value (12) not in expected range [0, 4)',
635 'Warning: while converting VCCLCompilerTool/BrowseInformation to '
636 'MSBuild, index value (21) not in expected range [0, 3)',
637 'Warning: while converting VCCLCompilerTool/UsePrecompiledHeader to '
638 'MSBuild, index value (13) not in expected range [0, 3)',
639 'Warning: while converting VCCLCompilerTool/GeneratePreprocessedFile to '
640 'MSBuild, value must be one of [0, 1, 2]; got 14',
641
642 'Warning: while converting VCLinkerTool/Driver to '
643 'MSBuild, index value (10) not in expected range [0, 4)',
644 'Warning: while converting VCLinkerTool/LinkTimeCodeGeneration to '
645 'MSBuild, index value (31) not in expected range [0, 5)',
646 'Warning: while converting VCLinkerTool/ErrorReporting to '
647 'MSBuild, index value (21) not in expected range [0, 3)',
648 'Warning: while converting VCLinkerTool/FixedBaseAddress to '
649 'MSBuild, index value (6) not in expected range [0, 3)',
650 ])
651
652 def testConvertToMSBuildSettings_full_synthetic(self):
653 """Tests conversion of all the MSBuild settings."""
654 msvs_settings = {
655 'VCCLCompilerTool': {
656 'AdditionalIncludeDirectories': 'folder1;folder2;folder3',
657 'AdditionalOptions': 'a_string',
658 'AdditionalUsingDirectories': 'folder1;folder2;folder3',
659 'AssemblerListingLocation': 'a_file_name',
660 'AssemblerOutput': '0',
661 'BasicRuntimeChecks': '1',
662 'BrowseInformation': '2',
663 'BrowseInformationFile': 'a_file_name',
664 'BufferSecurityCheck': 'true',
665 'CallingConvention': '0',
666 'CompileAs': '1',
667 'DebugInformationFormat': '4',
668 'DefaultCharIsUnsigned': 'true',
669 'Detect64BitPortabilityProblems': 'true',
670 'DisableLanguageExtensions': 'true',
671 'DisableSpecificWarnings': 'd1;d2;d3',
672 'EnableEnhancedInstructionSet': '0',
673 'EnableFiberSafeOptimizations': 'true',
674 'EnableFunctionLevelLinking': 'true',
675 'EnableIntrinsicFunctions': 'true',
676 'EnablePREfast': 'true',
677 'ErrorReporting': '1',
678 'ExceptionHandling': '2',
679 'ExpandAttributedSource': 'true',
680 'FavorSizeOrSpeed': '0',
681 'FloatingPointExceptions': 'true',
682 'FloatingPointModel': '1',
683 'ForceConformanceInForLoopScope': 'true',
684 'ForcedIncludeFiles': 'file1;file2;file3',
685 'ForcedUsingFiles': 'file1;file2;file3',
686 'GeneratePreprocessedFile': '1',
687 'GenerateXMLDocumentationFiles': 'true',
688 'IgnoreStandardIncludePath': 'true',
689 'InlineFunctionExpansion': '2',
690 'KeepComments': 'true',
691 'MinimalRebuild': 'true',
692 'ObjectFile': 'a_file_name',
693 'OmitDefaultLibName': 'true',
694 'OmitFramePointers': 'true',
695 'OpenMP': 'true',
696 'Optimization': '3',
697 'PrecompiledHeaderFile': 'a_file_name',
698 'PrecompiledHeaderThrough': 'a_file_name',
699 'PreprocessorDefinitions': 'd1;d2;d3',
700 'ProgramDataBaseFileName': 'a_file_name',
701 'RuntimeLibrary': '0',
702 'RuntimeTypeInfo': 'true',
703 'ShowIncludes': 'true',
704 'SmallerTypeCheck': 'true',
705 'StringPooling': 'true',
706 'StructMemberAlignment': '1',
707 'SuppressStartupBanner': 'true',
708 'TreatWChar_tAsBuiltInType': 'true',
709 'UndefineAllPreprocessorDefinitions': 'true',
710 'UndefinePreprocessorDefinitions': 'd1;d2;d3',
711 'UseFullPaths': 'true',
712 'UsePrecompiledHeader': '1',
713 'UseUnicodeResponseFiles': 'true',
714 'WarnAsError': 'true',
715 'WarningLevel': '2',
716 'WholeProgramOptimization': 'true',
717 'XMLDocumentationFileName': 'a_file_name'},
718 'VCLinkerTool': {
719 'AdditionalDependencies': 'file1;file2;file3',
720 'AdditionalLibraryDirectories': 'folder1;folder2;folder3',
721 'AdditionalLibraryDirectories_excluded': 'folder1;folder2;folder3',
722 'AdditionalManifestDependencies': 'file1;file2;file3',
723 'AdditionalOptions': 'a_string',
724 'AddModuleNamesToAssembly': 'file1;file2;file3',
725 'AllowIsolation': 'true',
726 'AssemblyDebug': '0',
727 'AssemblyLinkResource': 'file1;file2;file3',
728 'BaseAddress': 'a_string',
729 'CLRImageType': '1',
730 'CLRThreadAttribute': '2',
731 'CLRUnmanagedCodeCheck': 'true',
732 'DataExecutionPrevention': '0',
733 'DelayLoadDLLs': 'file1;file2;file3',
734 'DelaySign': 'true',
735 'Driver': '1',
736 'EmbedManagedResourceFile': 'file1;file2;file3',
737 'EnableCOMDATFolding': '0',
738 'EnableUAC': 'true',
739 'EntryPointSymbol': 'a_string',
740 'ErrorReporting': '0',
741 'FixedBaseAddress': '1',
742 'ForceSymbolReferences': 'file1;file2;file3',
743 'FunctionOrder': 'a_file_name',
744 'GenerateDebugInformation': 'true',
745 'GenerateManifest': 'true',
746 'GenerateMapFile': 'true',
747 'HeapCommitSize': 'a_string',
748 'HeapReserveSize': 'a_string',
749 'IgnoreAllDefaultLibraries': 'true',
750 'IgnoreDefaultLibraryNames': 'file1;file2;file3',
751 'IgnoreEmbeddedIDL': 'true',
752 'IgnoreImportLibrary': 'true',
753 'ImportLibrary': 'a_file_name',
754 'KeyContainer': 'a_file_name',
755 'KeyFile': 'a_file_name',
756 'LargeAddressAware': '2',
757 'LinkIncremental': '1',
758 'LinkLibraryDependencies': 'true',
759 'LinkTimeCodeGeneration': '2',
760 'ManifestFile': 'a_file_name',
761 'MapExports': 'true',
762 'MapFileName': 'a_file_name',
763 'MergedIDLBaseFileName': 'a_file_name',
764 'MergeSections': 'a_string',
765 'MidlCommandFile': 'a_file_name',
766 'ModuleDefinitionFile': 'a_file_name',
767 'OptimizeForWindows98': '1',
768 'OptimizeReferences': '0',
769 'OutputFile': 'a_file_name',
770 'PerUserRedirection': 'true',
771 'Profile': 'true',
772 'ProfileGuidedDatabase': 'a_file_name',
773 'ProgramDatabaseFile': 'a_file_name',
774 'RandomizedBaseAddress': '1',
775 'RegisterOutput': 'true',
776 'ResourceOnlyDLL': 'true',
777 'SetChecksum': 'true',
778 'ShowProgress': '0',
779 'StackCommitSize': 'a_string',
780 'StackReserveSize': 'a_string',
781 'StripPrivateSymbols': 'a_file_name',
782 'SubSystem': '2',
783 'SupportUnloadOfDelayLoadedDLL': 'true',
784 'SuppressStartupBanner': 'true',
785 'SwapRunFromCD': 'true',
786 'SwapRunFromNet': 'true',
787 'TargetMachine': '3',
788 'TerminalServerAware': '2',
789 'TurnOffAssemblyGeneration': 'true',
790 'TypeLibraryFile': 'a_file_name',
791 'TypeLibraryResourceID': '33',
792 'UACExecutionLevel': '1',
793 'UACUIAccess': 'true',
794 'UseLibraryDependencyInputs': 'false',
795 'UseUnicodeResponseFiles': 'true',
796 'Version': 'a_string'},
797 'VCResourceCompilerTool': {
798 'AdditionalIncludeDirectories': 'folder1;folder2;folder3',
799 'AdditionalOptions': 'a_string',
800 'Culture': '1003',
801 'IgnoreStandardIncludePath': 'true',
802 'PreprocessorDefinitions': 'd1;d2;d3',
803 'ResourceOutputFileName': 'a_string',
804 'ShowProgress': 'true',
805 'SuppressStartupBanner': 'true',
806 'UndefinePreprocessorDefinitions': 'd1;d2;d3'},
807 'VCMIDLTool': {
808 'AdditionalIncludeDirectories': 'folder1;folder2;folder3',
809 'AdditionalOptions': 'a_string',
810 'CPreprocessOptions': 'a_string',
811 'DefaultCharType': '0',
812 'DLLDataFileName': 'a_file_name',
813 'EnableErrorChecks': '2',
814 'ErrorCheckAllocations': 'true',
815 'ErrorCheckBounds': 'true',
816 'ErrorCheckEnumRange': 'true',
817 'ErrorCheckRefPointers': 'true',
818 'ErrorCheckStubData': 'true',
819 'GenerateStublessProxies': 'true',
820 'GenerateTypeLibrary': 'true',
821 'HeaderFileName': 'a_file_name',
822 'IgnoreStandardIncludePath': 'true',
823 'InterfaceIdentifierFileName': 'a_file_name',
824 'MkTypLibCompatible': 'true',
825 'OutputDirectory': 'a_string',
826 'PreprocessorDefinitions': 'd1;d2;d3',
827 'ProxyFileName': 'a_file_name',
828 'RedirectOutputAndErrors': 'a_file_name',
829 'StructMemberAlignment': '3',
830 'SuppressStartupBanner': 'true',
831 'TargetEnvironment': '1',
832 'TypeLibraryName': 'a_file_name',
833 'UndefinePreprocessorDefinitions': 'd1;d2;d3',
834 'ValidateParameters': 'true',
835 'WarnAsError': 'true',
836 'WarningLevel': '4'},
837 'VCLibrarianTool': {
838 'AdditionalDependencies': 'file1;file2;file3',
839 'AdditionalLibraryDirectories': 'folder1;folder2;folder3',
840 'AdditionalLibraryDirectories_excluded': 'folder1;folder2;folder3',
841 'AdditionalOptions': 'a_string',
842 'ExportNamedFunctions': 'd1;d2;d3',
843 'ForceSymbolReferences': 'a_string',
844 'IgnoreAllDefaultLibraries': 'true',
845 'IgnoreSpecificDefaultLibraries': 'file1;file2;file3',
846 'LinkLibraryDependencies': 'true',
847 'ModuleDefinitionFile': 'a_file_name',
848 'OutputFile': 'a_file_name',
849 'SuppressStartupBanner': 'true',
850 'UseUnicodeResponseFiles': 'true'},
851 'VCManifestTool': {
852 'AdditionalManifestFiles': 'file1;file2;file3',
853 'AdditionalOptions': 'a_string',
854 'AssemblyIdentity': 'a_string',
855 'ComponentFileName': 'a_file_name',
856 'DependencyInformationFile': 'a_file_name',
857 'EmbedManifest': 'true',
858 'GenerateCatalogFiles': 'true',
859 'InputResourceManifests': 'a_string',
860 'ManifestResourceFile': 'my_name',
861 'OutputManifestFile': 'a_file_name',
862 'RegistrarScriptFile': 'a_file_name',
863 'ReplacementsFile': 'a_file_name',
864 'SuppressStartupBanner': 'true',
865 'TypeLibraryFile': 'a_file_name',
866 'UpdateFileHashes': 'true',
867 'UpdateFileHashesSearchPath': 'a_file_name',
868 'UseFAT32Workaround': 'true',
869 'UseUnicodeResponseFiles': 'true',
870 'VerboseOutput': 'true'}}
871 expected_msbuild_settings = {
872 'ClCompile': {
873 'AdditionalIncludeDirectories': 'folder1;folder2;folder3',
874 'AdditionalOptions': 'a_string /J',
875 'AdditionalUsingDirectories': 'folder1;folder2;folder3',
876 'AssemblerListingLocation': 'a_file_name',
877 'AssemblerOutput': 'NoListing',
878 'BasicRuntimeChecks': 'StackFrameRuntimeCheck',
879 'BrowseInformation': 'true',
880 'BrowseInformationFile': 'a_file_name',
881 'BufferSecurityCheck': 'true',
882 'CallingConvention': 'Cdecl',
883 'CompileAs': 'CompileAsC',
884 'DebugInformationFormat': 'EditAndContinue',
885 'DisableLanguageExtensions': 'true',
886 'DisableSpecificWarnings': 'd1;d2;d3',
887 'EnableEnhancedInstructionSet': 'NotSet',
888 'EnableFiberSafeOptimizations': 'true',
889 'EnablePREfast': 'true',
890 'ErrorReporting': 'Prompt',
891 'ExceptionHandling': 'Async',
892 'ExpandAttributedSource': 'true',
893 'FavorSizeOrSpeed': 'Neither',
894 'FloatingPointExceptions': 'true',
895 'FloatingPointModel': 'Strict',
896 'ForceConformanceInForLoopScope': 'true',
897 'ForcedIncludeFiles': 'file1;file2;file3',
898 'ForcedUsingFiles': 'file1;file2;file3',
899 'FunctionLevelLinking': 'true',
900 'GenerateXMLDocumentationFiles': 'true',
901 'IgnoreStandardIncludePath': 'true',
902 'InlineFunctionExpansion': 'AnySuitable',
903 'IntrinsicFunctions': 'true',
904 'MinimalRebuild': 'true',
905 'ObjectFileName': 'a_file_name',
906 'OmitDefaultLibName': 'true',
907 'OmitFramePointers': 'true',
908 'OpenMPSupport': 'true',
909 'Optimization': 'Full',
910 'PrecompiledHeader': 'Create',
911 'PrecompiledHeaderFile': 'a_file_name',
912 'PrecompiledHeaderOutputFile': 'a_file_name',
913 'PreprocessKeepComments': 'true',
914 'PreprocessorDefinitions': 'd1;d2;d3',
915 'PreprocessSuppressLineNumbers': 'false',
916 'PreprocessToFile': 'true',
917 'ProgramDataBaseFileName': 'a_file_name',
918 'RuntimeLibrary': 'MultiThreaded',
919 'RuntimeTypeInfo': 'true',
920 'ShowIncludes': 'true',
921 'SmallerTypeCheck': 'true',
922 'StringPooling': 'true',
923 'StructMemberAlignment': '1Byte',
924 'SuppressStartupBanner': 'true',
925 'TreatWarningAsError': 'true',
926 'TreatWChar_tAsBuiltInType': 'true',
927 'UndefineAllPreprocessorDefinitions': 'true',
928 'UndefinePreprocessorDefinitions': 'd1;d2;d3',
929 'UseFullPaths': 'true',
930 'WarningLevel': 'Level2',
931 'WholeProgramOptimization': 'true',
932 'XMLDocumentationFileName': 'a_file_name'},
933 'Link': {
934 'AdditionalDependencies': 'file1;file2;file3',
935 'AdditionalLibraryDirectories': 'folder1;folder2;folder3',
936 'AdditionalManifestDependencies': 'file1;file2;file3',
937 'AdditionalOptions': 'a_string',
938 'AddModuleNamesToAssembly': 'file1;file2;file3',
939 'AllowIsolation': 'true',
940 'AssemblyDebug': '',
941 'AssemblyLinkResource': 'file1;file2;file3',
942 'BaseAddress': 'a_string',
943 'CLRImageType': 'ForceIJWImage',
944 'CLRThreadAttribute': 'STAThreadingAttribute',
945 'CLRUnmanagedCodeCheck': 'true',
946 'DataExecutionPrevention': '',
947 'DelayLoadDLLs': 'file1;file2;file3',
948 'DelaySign': 'true',
949 'Driver': 'Driver',
950 'EmbedManagedResourceFile': 'file1;file2;file3',
951 'EnableCOMDATFolding': '',
952 'EnableUAC': 'true',
953 'EntryPointSymbol': 'a_string',
954 'FixedBaseAddress': 'false',
955 'ForceSymbolReferences': 'file1;file2;file3',
956 'FunctionOrder': 'a_file_name',
957 'GenerateDebugInformation': 'true',
958 'GenerateMapFile': 'true',
959 'HeapCommitSize': 'a_string',
960 'HeapReserveSize': 'a_string',
961 'IgnoreAllDefaultLibraries': 'true',
962 'IgnoreEmbeddedIDL': 'true',
963 'IgnoreSpecificDefaultLibraries': 'file1;file2;file3',
964 'ImportLibrary': 'a_file_name',
965 'KeyContainer': 'a_file_name',
966 'KeyFile': 'a_file_name',
967 'LargeAddressAware': 'true',
968 'LinkErrorReporting': 'NoErrorReport',
969 'LinkTimeCodeGeneration': 'PGInstrument',
970 'ManifestFile': 'a_file_name',
971 'MapExports': 'true',
972 'MapFileName': 'a_file_name',
973 'MergedIDLBaseFileName': 'a_file_name',
974 'MergeSections': 'a_string',
975 'MidlCommandFile': 'a_file_name',
976 'ModuleDefinitionFile': 'a_file_name',
977 'NoEntryPoint': 'true',
978 'OptimizeReferences': '',
979 'OutputFile': 'a_file_name',
980 'PerUserRedirection': 'true',
981 'Profile': 'true',
982 'ProfileGuidedDatabase': 'a_file_name',
983 'ProgramDatabaseFile': 'a_file_name',
984 'RandomizedBaseAddress': 'false',
985 'RegisterOutput': 'true',
986 'SetChecksum': 'true',
987 'ShowProgress': 'NotSet',
988 'StackCommitSize': 'a_string',
989 'StackReserveSize': 'a_string',
990 'StripPrivateSymbols': 'a_file_name',
991 'SubSystem': 'Windows',
992 'SupportUnloadOfDelayLoadedDLL': 'true',
993 'SuppressStartupBanner': 'true',
994 'SwapRunFromCD': 'true',
995 'SwapRunFromNET': 'true',
996 'TargetMachine': 'MachineARM',
997 'TerminalServerAware': 'true',
998 'TurnOffAssemblyGeneration': 'true',
999 'TypeLibraryFile': 'a_file_name',
1000 'TypeLibraryResourceID': '33',
1001 'UACExecutionLevel': 'HighestAvailable',
1002 'UACUIAccess': 'true',
1003 'Version': 'a_string'},
1004 'ResourceCompile': {
1005 'AdditionalIncludeDirectories': 'folder1;folder2;folder3',
1006 'AdditionalOptions': 'a_string',
1007 'Culture': '0x03eb',
1008 'IgnoreStandardIncludePath': 'true',
1009 'PreprocessorDefinitions': 'd1;d2;d3',
1010 'ResourceOutputFileName': 'a_string',
1011 'ShowProgress': 'true',
1012 'SuppressStartupBanner': 'true',
1013 'UndefinePreprocessorDefinitions': 'd1;d2;d3'},
1014 'Midl': {
1015 'AdditionalIncludeDirectories': 'folder1;folder2;folder3',
1016 'AdditionalOptions': 'a_string',
1017 'CPreprocessOptions': 'a_string',
1018 'DefaultCharType': 'Unsigned',
1019 'DllDataFileName': 'a_file_name',
1020 'EnableErrorChecks': 'All',
1021 'ErrorCheckAllocations': 'true',
1022 'ErrorCheckBounds': 'true',
1023 'ErrorCheckEnumRange': 'true',
1024 'ErrorCheckRefPointers': 'true',
1025 'ErrorCheckStubData': 'true',
1026 'GenerateStublessProxies': 'true',
1027 'GenerateTypeLibrary': 'true',
1028 'HeaderFileName': 'a_file_name',
1029 'IgnoreStandardIncludePath': 'true',
1030 'InterfaceIdentifierFileName': 'a_file_name',
1031 'MkTypLibCompatible': 'true',
1032 'OutputDirectory': 'a_string',
1033 'PreprocessorDefinitions': 'd1;d2;d3',
1034 'ProxyFileName': 'a_file_name',
1035 'RedirectOutputAndErrors': 'a_file_name',
1036 'StructMemberAlignment': '4',
1037 'SuppressStartupBanner': 'true',
1038 'TargetEnvironment': 'Win32',
1039 'TypeLibraryName': 'a_file_name',
1040 'UndefinePreprocessorDefinitions': 'd1;d2;d3',
1041 'ValidateAllParameters': 'true',
1042 'WarnAsError': 'true',
1043 'WarningLevel': '4'},
1044 'Lib': {
1045 'AdditionalDependencies': 'file1;file2;file3',
1046 'AdditionalLibraryDirectories': 'folder1;folder2;folder3',
1047 'AdditionalOptions': 'a_string',
1048 'ExportNamedFunctions': 'd1;d2;d3',
1049 'ForceSymbolReferences': 'a_string',
1050 'IgnoreAllDefaultLibraries': 'true',
1051 'IgnoreSpecificDefaultLibraries': 'file1;file2;file3',
1052 'ModuleDefinitionFile': 'a_file_name',
1053 'OutputFile': 'a_file_name',
1054 'SuppressStartupBanner': 'true',
1055 'UseUnicodeResponseFiles': 'true'},
1056 'Mt': {
1057 'AdditionalManifestFiles': 'file1;file2;file3',
1058 'AdditionalOptions': 'a_string',
1059 'AssemblyIdentity': 'a_string',
1060 'ComponentFileName': 'a_file_name',
1061 'GenerateCatalogFiles': 'true',
1062 'InputResourceManifests': 'a_string',
1063 'OutputManifestFile': 'a_file_name',
1064 'RegistrarScriptFile': 'a_file_name',
1065 'ReplacementsFile': 'a_file_name',
1066 'SuppressStartupBanner': 'true',
1067 'TypeLibraryFile': 'a_file_name',
1068 'UpdateFileHashes': 'true',
1069 'UpdateFileHashesSearchPath': 'a_file_name',
1070 'VerboseOutput': 'true'},
1071 'ManifestResourceCompile': {
1072 'ResourceOutputFileName': 'my_name'},
1073 'ProjectReference': {
1074 'LinkLibraryDependencies': 'true',
1075 'UseLibraryDependencyInputs': 'false'},
1076 '': {
1077 'EmbedManifest': 'true',
1078 'GenerateManifest': 'true',
1079 'IgnoreImportLibrary': 'true',
1080 'LinkIncremental': 'false'}}
1081 actual_msbuild_settings = MSVSSettings.ConvertToMSBuildSettings(
1082 msvs_settings,
1083 self.stderr)
1084 self.assertEqual(expected_msbuild_settings, actual_msbuild_settings)
1085 self._ExpectedWarnings([])
1086
1087 def testConvertToMSBuildSettings_actual(self):
1088 """Tests the conversion of an actual project.
1089
1090 A VS2008 project with most of the options defined was created through the
1091 VS2008 IDE. It was then converted to VS2010. The tool settings found in
1092 the .vcproj and .vcxproj files were converted to the two dictionaries
1093 msvs_settings and expected_msbuild_settings.
1094
1095 Note that for many settings, the VS2010 converter adds macros like
1096 %(AdditionalIncludeDirectories) to make sure than inherited values are
1097 included. Since the Gyp projects we generate do not use inheritance,
1098 we removed these macros. They were:
1099 ClCompile:
1100 AdditionalIncludeDirectories: ';%(AdditionalIncludeDirectories)'
1101 AdditionalOptions: ' %(AdditionalOptions)'
1102 AdditionalUsingDirectories: ';%(AdditionalUsingDirectories)'
1103 DisableSpecificWarnings: ';%(DisableSpecificWarnings)',
1104 ForcedIncludeFiles: ';%(ForcedIncludeFiles)',
1105 ForcedUsingFiles: ';%(ForcedUsingFiles)',
1106 PreprocessorDefinitions: ';%(PreprocessorDefinitions)',
1107 UndefinePreprocessorDefinitions:
1108 ';%(UndefinePreprocessorDefinitions)',
1109 Link:
1110 AdditionalDependencies: ';%(AdditionalDependencies)',
1111 AdditionalLibraryDirectories: ';%(AdditionalLibraryDirectories)',
1112 AdditionalManifestDependencies:
1113 ';%(AdditionalManifestDependencies)',
1114 AdditionalOptions: ' %(AdditionalOptions)',
1115 AddModuleNamesToAssembly: ';%(AddModuleNamesToAssembly)',
1116 AssemblyLinkResource: ';%(AssemblyLinkResource)',
1117 DelayLoadDLLs: ';%(DelayLoadDLLs)',
1118 EmbedManagedResourceFile: ';%(EmbedManagedResourceFile)',
1119 ForceSymbolReferences: ';%(ForceSymbolReferences)',
1120 IgnoreSpecificDefaultLibraries:
1121 ';%(IgnoreSpecificDefaultLibraries)',
1122 ResourceCompile:
1123 AdditionalIncludeDirectories: ';%(AdditionalIncludeDirectories)',
1124 AdditionalOptions: ' %(AdditionalOptions)',
1125 PreprocessorDefinitions: ';%(PreprocessorDefinitions)',
1126 Mt:
1127 AdditionalManifestFiles: ';%(AdditionalManifestFiles)',
1128 AdditionalOptions: ' %(AdditionalOptions)',
1129 InputResourceManifests: ';%(InputResourceManifests)',
1130 """
1131 msvs_settings = {
1132 'VCCLCompilerTool': {
1133 'AdditionalIncludeDirectories': 'dir1',
1134 'AdditionalOptions': '/more',
1135 'AdditionalUsingDirectories': 'test',
1136 'AssemblerListingLocation': '$(IntDir)\\a',
1137 'AssemblerOutput': '1',
1138 'BasicRuntimeChecks': '3',
1139 'BrowseInformation': '1',
1140 'BrowseInformationFile': '$(IntDir)\\e',
1141 'BufferSecurityCheck': 'false',
1142 'CallingConvention': '1',
1143 'CompileAs': '1',
1144 'DebugInformationFormat': '4',
1145 'DefaultCharIsUnsigned': 'true',
1146 'Detect64BitPortabilityProblems': 'true',
1147 'DisableLanguageExtensions': 'true',
1148 'DisableSpecificWarnings': 'abc',
1149 'EnableEnhancedInstructionSet': '1',
1150 'EnableFiberSafeOptimizations': 'true',
1151 'EnableFunctionLevelLinking': 'true',
1152 'EnableIntrinsicFunctions': 'true',
1153 'EnablePREfast': 'true',
1154 'ErrorReporting': '2',
1155 'ExceptionHandling': '2',
1156 'ExpandAttributedSource': 'true',
1157 'FavorSizeOrSpeed': '2',
1158 'FloatingPointExceptions': 'true',
1159 'FloatingPointModel': '1',
1160 'ForceConformanceInForLoopScope': 'false',
1161 'ForcedIncludeFiles': 'def',
1162 'ForcedUsingFiles': 'ge',
1163 'GeneratePreprocessedFile': '2',
1164 'GenerateXMLDocumentationFiles': 'true',
1165 'IgnoreStandardIncludePath': 'true',
1166 'InlineFunctionExpansion': '1',
1167 'KeepComments': 'true',
1168 'MinimalRebuild': 'true',
1169 'ObjectFile': '$(IntDir)\\b',
1170 'OmitDefaultLibName': 'true',
1171 'OmitFramePointers': 'true',
1172 'OpenMP': 'true',
1173 'Optimization': '3',
1174 'PrecompiledHeaderFile': '$(IntDir)\\$(TargetName).pche',
1175 'PrecompiledHeaderThrough': 'StdAfx.hd',
1176 'PreprocessorDefinitions': 'WIN32;_DEBUG;_CONSOLE',
1177 'ProgramDataBaseFileName': '$(IntDir)\\vc90b.pdb',
1178 'RuntimeLibrary': '3',
1179 'RuntimeTypeInfo': 'false',
1180 'ShowIncludes': 'true',
1181 'SmallerTypeCheck': 'true',
1182 'StringPooling': 'true',
1183 'StructMemberAlignment': '3',
1184 'SuppressStartupBanner': 'false',
1185 'TreatWChar_tAsBuiltInType': 'false',
1186 'UndefineAllPreprocessorDefinitions': 'true',
1187 'UndefinePreprocessorDefinitions': 'wer',
1188 'UseFullPaths': 'true',
1189 'UsePrecompiledHeader': '0',
1190 'UseUnicodeResponseFiles': 'false',
1191 'WarnAsError': 'true',
1192 'WarningLevel': '3',
1193 'WholeProgramOptimization': 'true',
1194 'XMLDocumentationFileName': '$(IntDir)\\c'},
1195 'VCLinkerTool': {
1196 'AdditionalDependencies': 'zx',
1197 'AdditionalLibraryDirectories': 'asd',
1198 'AdditionalManifestDependencies': 's2',
1199 'AdditionalOptions': '/mor2',
1200 'AddModuleNamesToAssembly': 'd1',
1201 'AllowIsolation': 'false',
1202 'AssemblyDebug': '1',
1203 'AssemblyLinkResource': 'd5',
1204 'BaseAddress': '23423',
1205 'CLRImageType': '3',
1206 'CLRThreadAttribute': '1',
1207 'CLRUnmanagedCodeCheck': 'true',
1208 'DataExecutionPrevention': '0',
1209 'DelayLoadDLLs': 'd4',
1210 'DelaySign': 'true',
1211 'Driver': '2',
1212 'EmbedManagedResourceFile': 'd2',
1213 'EnableCOMDATFolding': '1',
1214 'EnableUAC': 'false',
1215 'EntryPointSymbol': 'f5',
1216 'ErrorReporting': '2',
1217 'FixedBaseAddress': '1',
1218 'ForceSymbolReferences': 'd3',
1219 'FunctionOrder': 'fssdfsd',
1220 'GenerateDebugInformation': 'true',
1221 'GenerateManifest': 'false',
1222 'GenerateMapFile': 'true',
1223 'HeapCommitSize': '13',
1224 'HeapReserveSize': '12',
1225 'IgnoreAllDefaultLibraries': 'true',
1226 'IgnoreDefaultLibraryNames': 'flob;flok',
1227 'IgnoreEmbeddedIDL': 'true',
1228 'IgnoreImportLibrary': 'true',
1229 'ImportLibrary': 'f4',
1230 'KeyContainer': 'f7',
1231 'KeyFile': 'f6',
1232 'LargeAddressAware': '2',
1233 'LinkIncremental': '0',
1234 'LinkLibraryDependencies': 'false',
1235 'LinkTimeCodeGeneration': '1',
1236 'ManifestFile':
1237 '$(IntDir)\\$(TargetFileName).2intermediate.manifest',
1238 'MapExports': 'true',
1239 'MapFileName': 'd5',
1240 'MergedIDLBaseFileName': 'f2',
1241 'MergeSections': 'f5',
1242 'MidlCommandFile': 'f1',
1243 'ModuleDefinitionFile': 'sdsd',
1244 'OptimizeForWindows98': '2',
1245 'OptimizeReferences': '2',
1246 'OutputFile': '$(OutDir)\\$(ProjectName)2.exe',
1247 'PerUserRedirection': 'true',
1248 'Profile': 'true',
1249 'ProfileGuidedDatabase': '$(TargetDir)$(TargetName).pgdd',
1250 'ProgramDatabaseFile': 'Flob.pdb',
1251 'RandomizedBaseAddress': '1',
1252 'RegisterOutput': 'true',
1253 'ResourceOnlyDLL': 'true',
1254 'SetChecksum': 'false',
1255 'ShowProgress': '1',
1256 'StackCommitSize': '15',
1257 'StackReserveSize': '14',
1258 'StripPrivateSymbols': 'd3',
1259 'SubSystem': '1',
1260 'SupportUnloadOfDelayLoadedDLL': 'true',
1261 'SuppressStartupBanner': 'false',
1262 'SwapRunFromCD': 'true',
1263 'SwapRunFromNet': 'true',
1264 'TargetMachine': '1',
1265 'TerminalServerAware': '1',
1266 'TurnOffAssemblyGeneration': 'true',
1267 'TypeLibraryFile': 'f3',
1268 'TypeLibraryResourceID': '12',
1269 'UACExecutionLevel': '2',
1270 'UACUIAccess': 'true',
1271 'UseLibraryDependencyInputs': 'true',
1272 'UseUnicodeResponseFiles': 'false',
1273 'Version': '333'},
1274 'VCResourceCompilerTool': {
1275 'AdditionalIncludeDirectories': 'f3',
1276 'AdditionalOptions': '/more3',
1277 'Culture': '3084',
1278 'IgnoreStandardIncludePath': 'true',
1279 'PreprocessorDefinitions': '_UNICODE;UNICODE2',
1280 'ResourceOutputFileName': '$(IntDir)/$(InputName)3.res',
1281 'ShowProgress': 'true'},
1282 'VCManifestTool': {
1283 'AdditionalManifestFiles': 'sfsdfsd',
1284 'AdditionalOptions': 'afdsdafsd',
1285 'AssemblyIdentity': 'sddfdsadfsa',
1286 'ComponentFileName': 'fsdfds',
1287 'DependencyInformationFile': '$(IntDir)\\mt.depdfd',
1288 'EmbedManifest': 'false',
1289 'GenerateCatalogFiles': 'true',
1290 'InputResourceManifests': 'asfsfdafs',
1291 'ManifestResourceFile':
1292 '$(IntDir)\\$(TargetFileName).embed.manifest.resfdsf',
1293 'OutputManifestFile': '$(TargetPath).manifestdfs',
1294 'RegistrarScriptFile': 'sdfsfd',
1295 'ReplacementsFile': 'sdffsd',
1296 'SuppressStartupBanner': 'false',
1297 'TypeLibraryFile': 'sfsd',
1298 'UpdateFileHashes': 'true',
1299 'UpdateFileHashesSearchPath': 'sfsd',
1300 'UseFAT32Workaround': 'true',
1301 'UseUnicodeResponseFiles': 'false',
1302 'VerboseOutput': 'true'}}
1303 expected_msbuild_settings = {
1304 'ClCompile': {
1305 'AdditionalIncludeDirectories': 'dir1',
1306 'AdditionalOptions': '/more /J',
1307 'AdditionalUsingDirectories': 'test',
1308 'AssemblerListingLocation': '$(IntDir)a',
1309 'AssemblerOutput': 'AssemblyCode',
1310 'BasicRuntimeChecks': 'EnableFastChecks',
1311 'BrowseInformation': 'true',
1312 'BrowseInformationFile': '$(IntDir)e',
1313 'BufferSecurityCheck': 'false',
1314 'CallingConvention': 'FastCall',
1315 'CompileAs': 'CompileAsC',
1316 'DebugInformationFormat': 'EditAndContinue',
1317 'DisableLanguageExtensions': 'true',
1318 'DisableSpecificWarnings': 'abc',
1319 'EnableEnhancedInstructionSet': 'StreamingSIMDExtensions',
1320 'EnableFiberSafeOptimizations': 'true',
1321 'EnablePREfast': 'true',
1322 'ErrorReporting': 'Queue',
1323 'ExceptionHandling': 'Async',
1324 'ExpandAttributedSource': 'true',
1325 'FavorSizeOrSpeed': 'Size',
1326 'FloatingPointExceptions': 'true',
1327 'FloatingPointModel': 'Strict',
1328 'ForceConformanceInForLoopScope': 'false',
1329 'ForcedIncludeFiles': 'def',
1330 'ForcedUsingFiles': 'ge',
1331 'FunctionLevelLinking': 'true',
1332 'GenerateXMLDocumentationFiles': 'true',
1333 'IgnoreStandardIncludePath': 'true',
1334 'InlineFunctionExpansion': 'OnlyExplicitInline',
1335 'IntrinsicFunctions': 'true',
1336 'MinimalRebuild': 'true',
1337 'ObjectFileName': '$(IntDir)b',
1338 'OmitDefaultLibName': 'true',
1339 'OmitFramePointers': 'true',
1340 'OpenMPSupport': 'true',
1341 'Optimization': 'Full',
1342 'PrecompiledHeader': 'NotUsing', # Actual conversion gives ''
1343 'PrecompiledHeaderFile': 'StdAfx.hd',
1344 'PrecompiledHeaderOutputFile': '$(IntDir)$(TargetName).pche',
1345 'PreprocessKeepComments': 'true',
1346 'PreprocessorDefinitions': 'WIN32;_DEBUG;_CONSOLE',
1347 'PreprocessSuppressLineNumbers': 'true',
1348 'PreprocessToFile': 'true',
1349 'ProgramDataBaseFileName': '$(IntDir)vc90b.pdb',
1350 'RuntimeLibrary': 'MultiThreadedDebugDLL',
1351 'RuntimeTypeInfo': 'false',
1352 'ShowIncludes': 'true',
1353 'SmallerTypeCheck': 'true',
1354 'StringPooling': 'true',
1355 'StructMemberAlignment': '4Bytes',
1356 'SuppressStartupBanner': 'false',
1357 'TreatWarningAsError': 'true',
1358 'TreatWChar_tAsBuiltInType': 'false',
1359 'UndefineAllPreprocessorDefinitions': 'true',
1360 'UndefinePreprocessorDefinitions': 'wer',
1361 'UseFullPaths': 'true',
1362 'WarningLevel': 'Level3',
1363 'WholeProgramOptimization': 'true',
1364 'XMLDocumentationFileName': '$(IntDir)c'},
1365 'Link': {
1366 'AdditionalDependencies': 'zx',
1367 'AdditionalLibraryDirectories': 'asd',
1368 'AdditionalManifestDependencies': 's2',
1369 'AdditionalOptions': '/mor2',
1370 'AddModuleNamesToAssembly': 'd1',
1371 'AllowIsolation': 'false',
1372 'AssemblyDebug': 'true',
1373 'AssemblyLinkResource': 'd5',
1374 'BaseAddress': '23423',
1375 'CLRImageType': 'ForceSafeILImage',
1376 'CLRThreadAttribute': 'MTAThreadingAttribute',
1377 'CLRUnmanagedCodeCheck': 'true',
1378 'DataExecutionPrevention': '',
1379 'DelayLoadDLLs': 'd4',
1380 'DelaySign': 'true',
1381 'Driver': 'UpOnly',
1382 'EmbedManagedResourceFile': 'd2',
1383 'EnableCOMDATFolding': 'false',
1384 'EnableUAC': 'false',
1385 'EntryPointSymbol': 'f5',
1386 'FixedBaseAddress': 'false',
1387 'ForceSymbolReferences': 'd3',
1388 'FunctionOrder': 'fssdfsd',
1389 'GenerateDebugInformation': 'true',
1390 'GenerateMapFile': 'true',
1391 'HeapCommitSize': '13',
1392 'HeapReserveSize': '12',
1393 'IgnoreAllDefaultLibraries': 'true',
1394 'IgnoreEmbeddedIDL': 'true',
1395 'IgnoreSpecificDefaultLibraries': 'flob;flok',
1396 'ImportLibrary': 'f4',
1397 'KeyContainer': 'f7',
1398 'KeyFile': 'f6',
1399 'LargeAddressAware': 'true',
1400 'LinkErrorReporting': 'QueueForNextLogin',
1401 'LinkTimeCodeGeneration': 'UseLinkTimeCodeGeneration',
1402 'ManifestFile': '$(IntDir)$(TargetFileName).2intermediate.manifest',
1403 'MapExports': 'true',
1404 'MapFileName': 'd5',
1405 'MergedIDLBaseFileName': 'f2',
1406 'MergeSections': 'f5',
1407 'MidlCommandFile': 'f1',
1408 'ModuleDefinitionFile': 'sdsd',
1409 'NoEntryPoint': 'true',
1410 'OptimizeReferences': 'true',
1411 'OutputFile': '$(OutDir)$(ProjectName)2.exe',
1412 'PerUserRedirection': 'true',
1413 'Profile': 'true',
1414 'ProfileGuidedDatabase': '$(TargetDir)$(TargetName).pgdd',
1415 'ProgramDatabaseFile': 'Flob.pdb',
1416 'RandomizedBaseAddress': 'false',
1417 'RegisterOutput': 'true',
1418 'SetChecksum': 'false',
1419 'ShowProgress': 'LinkVerbose',
1420 'StackCommitSize': '15',
1421 'StackReserveSize': '14',
1422 'StripPrivateSymbols': 'd3',
1423 'SubSystem': 'Console',
1424 'SupportUnloadOfDelayLoadedDLL': 'true',
1425 'SuppressStartupBanner': 'false',
1426 'SwapRunFromCD': 'true',
1427 'SwapRunFromNET': 'true',
1428 'TargetMachine': 'MachineX86',
1429 'TerminalServerAware': 'false',
1430 'TurnOffAssemblyGeneration': 'true',
1431 'TypeLibraryFile': 'f3',
1432 'TypeLibraryResourceID': '12',
1433 'UACExecutionLevel': 'RequireAdministrator',
1434 'UACUIAccess': 'true',
1435 'Version': '333'},
1436 'ResourceCompile': {
1437 'AdditionalIncludeDirectories': 'f3',
1438 'AdditionalOptions': '/more3',
1439 'Culture': '0x0c0c',
1440 'IgnoreStandardIncludePath': 'true',
1441 'PreprocessorDefinitions': '_UNICODE;UNICODE2',
1442 'ResourceOutputFileName': '$(IntDir)%(Filename)3.res',
1443 'ShowProgress': 'true'},
1444 'Mt': {
1445 'AdditionalManifestFiles': 'sfsdfsd',
1446 'AdditionalOptions': 'afdsdafsd',
1447 'AssemblyIdentity': 'sddfdsadfsa',
1448 'ComponentFileName': 'fsdfds',
1449 'GenerateCatalogFiles': 'true',
1450 'InputResourceManifests': 'asfsfdafs',
1451 'OutputManifestFile': '$(TargetPath).manifestdfs',
1452 'RegistrarScriptFile': 'sdfsfd',
1453 'ReplacementsFile': 'sdffsd',
1454 'SuppressStartupBanner': 'false',
1455 'TypeLibraryFile': 'sfsd',
1456 'UpdateFileHashes': 'true',
1457 'UpdateFileHashesSearchPath': 'sfsd',
1458 'VerboseOutput': 'true'},
1459 'ProjectReference': {
1460 'LinkLibraryDependencies': 'false',
1461 'UseLibraryDependencyInputs': 'true'},
1462 '': {
1463 'EmbedManifest': 'false',
1464 'GenerateManifest': 'false',
1465 'IgnoreImportLibrary': 'true',
1466 'LinkIncremental': ''
1467 },
1468 'ManifestResourceCompile': {
1469 'ResourceOutputFileName':
1470 '$(IntDir)$(TargetFileName).embed.manifest.resfdsf'}
1471 }
1472 actual_msbuild_settings = MSVSSettings.ConvertToMSBuildSettings(
1473 msvs_settings,
1474 self.stderr)
1475 self.assertEqual(expected_msbuild_settings, actual_msbuild_settings)
1476 self._ExpectedWarnings([])
1477
1478 if __name__ == '__main__':
1479 unittest.main()
77
88 import common
99 import xml.dom
10 import xml.dom.minidom
10 import xml_fix
1111
1212
1313 #------------------------------------------------------------------------------
7272 def Write(self, writer=common.WriteOnDiff):
7373 """Writes the tool file."""
7474 f = writer(self.tool_file_path)
75 fix = xml_fix.XmlFix()
7576 self.doc.writexml(f, encoding='Windows-1252', addindent=' ', newl='\r\n')
77 fix.Cleanup()
7678 f.close()
7779
7880 #------------------------------------------------------------------------------
1010 import re
1111 import socket # for gethostname
1212 import xml.dom
13 import xml.dom.minidom
13 import xml_fix
1414
1515
1616 #------------------------------------------------------------------------------
00 #!/usr/bin/python
1
2 # Copyright (c) 2009 Google Inc. All rights reserved.
1 # Copyright (c) 2011 The Chromium Authors. All rights reserved.
32 # Use of this source code is governed by a BSD-style license that can be
43 # found in the LICENSE file.
54
65 """Handle version information related to Visual Stuio."""
76
7 import errno
88 import os
99 import re
1010 import subprocess
1515 """Information regarding a version of Visual Studio."""
1616
1717 def __init__(self, short_name, description,
18 solution_version, project_version, flat_sln):
18 solution_version, project_version, flat_sln, uses_vcxproj):
1919 self.short_name = short_name
2020 self.description = description
2121 self.solution_version = solution_version
2222 self.project_version = project_version
2323 self.flat_sln = flat_sln
24 self.uses_vcxproj = uses_vcxproj
2425
2526 def ShortName(self):
2627 return self.short_name
3435 return self.solution_version
3536
3637 def ProjectVersion(self):
37 """Get the version number of the vcproj files."""
38 """Get the version number of the vcproj or vcxproj files."""
3839 return self.project_version
3940
4041 def FlatSolution(self):
4142 return self.flat_sln
4243
43
44 def _RegistryGetValue(key, value):
45 """Use reg.exe to read a paricular key.
44 def UsesVcxproj(self):
45 """Returns true if this version uses a vcxproj file."""
46 return self.uses_vcxproj
47
48 def ProjectExtension(self):
49 """Returns the file extension for the project."""
50 return self.uses_vcxproj and '.vcxproj' or '.vcproj'
51
52 def _RegistryQueryBase(sysdir, key, value):
53 """Use reg.exe to read a particular key.
4654
4755 While ideally we might use the win32 module, we would like gyp to be
4856 python neutral, so for instance cygwin python lacks this module.
4957
5058 Arguments:
59 sysdir: The system subdirectory to attempt to launch reg.exe from.
5160 key: The registry key to read from.
5261 value: The particular value to read.
5362 Return:
54 The contents there, or None for failure.
55 """
56 # Skip if not on Windows.
63 stdout from reg.exe, or None for failure.
64 """
65 # Skip if not on Windows or Python Win32 setup issue
5766 if sys.platform not in ('win32', 'cygwin'):
5867 return None
59 # Run reg.exe.
60 cmd = [os.path.join(os.environ.get('WINDIR', ''), 'System32', 'reg.exe'),
61 'query', key, '/v', value]
68 # Setup params to pass to and attempt to launch reg.exe
69 cmd = [os.path.join(os.environ.get('WINDIR', ''), sysdir, 'reg.exe'),
70 'query', key]
71 if value:
72 cmd.extend(['/v', value])
6273 p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
74 # Obtain the stdout from reg.exe, reading to the end so p.returncode is valid
75 # Note that the error text may be in [1] in some cases
6376 text = p.communicate()[0]
64 # Require a successful return value.
77 # Check return code from reg.exe; officially 0==success and 1==error
6578 if p.returncode:
6679 return None
80 return text
81
82 def _RegistryQuery(key, value=None):
83 """Use reg.exe to read a particular key through _RegistryQueryBase.
84
85 First tries to launch from %WinDir%\Sysnative to avoid WoW64 redirection. If
86 that fails, it falls back to System32. Sysnative is available on Vista and
87 up and available on Windows Server 2003 and XP through KB patch 942589. Note
88 that Sysnative will always fail if using 64-bit python due to it being a
89 virtual directory and System32 will work correctly in the first place.
90
91 KB 942589 - http://support.microsoft.com/kb/942589/en-us.
92
93 Arguments:
94 key: The registry key.
95 value: The particular registry value to read (optional).
96 Return:
97 stdout from reg.exe, or None for failure.
98 """
99 text = None
100 try:
101 text = _RegistryQueryBase('Sysnative', key, value)
102 except OSError, e:
103 if e.errno == errno.ENOENT:
104 text = _RegistryQueryBase('System32', key, value)
105 else:
106 raise
107 return text
108
109 def _RegistryGetValue(key, value):
110 """Use reg.exe to obtain the value of a registry key.
111
112 Args:
113 key: The registry key.
114 value: The particular registry value to read.
115 Return:
116 contents of the registry key's value, or None on failure.
117 """
118 text = _RegistryQuery(key, value)
119 if not text:
120 return None
67121 # Extract value.
68 match = re.search(r'REG_\w+[ ]+([^\r]+)\r\n', text)
122 match = re.search(r'REG_\w+\s+([^\r]+)\r\n', text)
69123 if not match:
70124 return None
71125 return match.group(1)
72126
127 def _RegistryKeyExists(key):
128 """Use reg.exe to see if a key exists.
129
130 Args:
131 key: The registry key to check.
132 Return:
133 True if the key exists
134 """
135 if not _RegistryQuery(key):
136 return False
137 return True
138
73139
74140 def _CreateVersion(name):
141 """Sets up MSVS project generation.
142
143 Setup is based off the GYP_MSVS_VERSION environment variable or whatever is
144 autodetected if GYP_MSVS_VERSION is not explicitly specified. If a version is
145 passed in that doesn't match a value in versions python will throw a error.
146 """
75147 versions = {
148 '2010': VisualStudioVersion('2010',
149 'Visual Studio 2010',
150 solution_version='11.00',
151 project_version='4.0',
152 flat_sln=False,
153 uses_vcxproj=True),
154 '2010e': VisualStudioVersion('2010e',
155 'Visual Studio 2010',
156 solution_version='11.00',
157 project_version='4.0',
158 flat_sln=True,
159 uses_vcxproj=True),
76160 '2008': VisualStudioVersion('2008',
77161 'Visual Studio 2008',
78162 solution_version='10.00',
79163 project_version='9.00',
80 flat_sln=False),
164 flat_sln=False,
165 uses_vcxproj=False),
81166 '2008e': VisualStudioVersion('2008e',
82167 'Visual Studio 2008',
83168 solution_version='10.00',
84169 project_version='9.00',
85 flat_sln=True),
170 flat_sln=True,
171 uses_vcxproj=False),
86172 '2005': VisualStudioVersion('2005',
87173 'Visual Studio 2005',
88174 solution_version='9.00',
89175 project_version='8.00',
90 flat_sln=False),
176 flat_sln=False,
177 uses_vcxproj=False),
91178 '2005e': VisualStudioVersion('2005e',
92179 'Visual Studio 2005',
93180 solution_version='9.00',
94181 project_version='8.00',
95 flat_sln=True),
182 flat_sln=True,
183 uses_vcxproj=False),
96184 }
97185 return versions[str(name)]
98186
104192 A list of visual studio versions installed in descending order of
105193 usage preference.
106194 Base this on the registry and a quick check if devenv.exe exists.
107 Only versions 8-9 are considered.
195 Only versions 8-10 are considered.
108196 Possibilities are:
109 2005 - Visual Studio 2005 (8)
110 2008 - Visual Studio 2008 (9)
111 """
112 version_to_year = {'8.0': '2005', '9.0': '2008'}
197 2005(e) - Visual Studio 2005 (8)
198 2008(e) - Visual Studio 2008 (9)
199 2010(e) - Visual Studio 2010 (10)
200 Where (e) is e for express editions of MSVS and blank otherwise.
201 """
202 version_to_year = {'8.0': '2005', '9.0': '2008', '10.0': '2010'}
113203 versions = []
114 for version in ('9.0', '8.0'):
115 # Get the install dir for this version.
116 key = r'HKLM\Software\Microsoft\VisualStudio\%s' % version
117 path = _RegistryGetValue(key, 'InstallDir')
118 if not path:
119 continue
120 # Check for full.
121 if os.path.exists(os.path.join(path, 'devenv.exe')):
122 # Add this one.
123 versions.append(_CreateVersion(version_to_year[version]))
124 # Check for express.
125 elif os.path.exists(os.path.join(path, 'vcexpress.exe')):
126 # Add this one.
127 versions.append(_CreateVersion(version_to_year[version] + 'e'))
204 # For now, prefer versions before VS2010
205 for version in ('9.0', '8.0', '10.0'):
206 # Check if VS2010 and later is installed as specified by
207 # http://msdn.microsoft.com/en-us/library/bb164659.aspx
208 keys = [r'HKLM\SOFTWARE\Microsoft\DevDiv\VS\Servicing\%s' % version,
209 r'HKLM\SOFTWARE\Wow6432Node\Microsoft\DevDiv\VS\Servicing\%s' % (
210 version)]
211 for index in range(len(keys)):
212 if not _RegistryKeyExists(keys[index]):
213 continue
214 # Check for express
215 if _RegistryKeyExists(keys[index] + '\\expbsln'):
216 # Add this one
217 versions.append(_CreateVersion(version_to_year[version] + 'e'))
218 else:
219 # Add this one
220 versions.append(_CreateVersion(version_to_year[version]))
221
222 # Old (pre-VS2010) method of searching for which VS version is installed
223 keys = [r'HKLM\Software\Microsoft\VisualStudio\%s' % version,
224 r'HKLM\Software\Wow6432Node\Microsoft\VisualStudio\%s' % version,
225 r'HKLM\Software\Microsoft\VCExpress\%s' % version,
226 r'HKLM\Software\Wow6432Node\Microsoft\VCExpress\%s' % version]
227 for index in range(len(keys)):
228 path = _RegistryGetValue(keys[index], 'InstallDir')
229 if not path:
230 continue
231 # Check for full.
232 if os.path.exists(os.path.join(path, 'devenv.exe')):
233 # Add this one.
234 versions.append(_CreateVersion(version_to_year[version]))
235 # Check for express.
236 elif os.path.exists(os.path.join(path, 'vcexpress.exe')):
237 # Add this one.
238 versions.append(_CreateVersion(version_to_year[version] + 'e'))
128239 return versions
129240
130241
264264 help='do not read options from environment variables')
265265 parser.add_option('--check', dest='check', action='store_true',
266266 help='check format of gyp files')
267 parser.add_option('--toplevel-dir', dest='toplevel_dir', action='store',
268 default=None, metavar='DIR', type='path',
269 help='directory to use as the root of the source tree')
267270 # --no-circular-check disables the check for circular relationships between
268271 # .gyp files. These relationships should not exist, but they've only been
269272 # observed to be harmful with the Xcode generator. Chromium's .gyp files
292295
293296 # TODO(thomasvl): add support for ~/.gyp/defaults
294297
295 (options, build_files_arg) = parser.parse_args(args)
298 options, build_files_arg = parser.parse_args(args)
296299 build_files = build_files_arg
297300
298301 if not options.formats:
326329 # Do an extra check to avoid work when we're not debugging.
327330 if DEBUG_GENERAL in gyp.debug.keys():
328331 DebugOutput(DEBUG_GENERAL, 'running with these options:')
329 for (option, value) in options.__dict__.items():
332 for option, value in sorted(options.__dict__.items()):
330333 if option[0] == '_':
331334 continue
332335 if isinstance(value, basestring):
369372 'temporary Chromium feature that will be removed. Use ' + \
370373 '--depth as a workaround.'
371374
375 # If toplevel-dir is not set, we assume that depth is the root of our source
376 # tree.
377 if not options.toplevel_dir:
378 options.toplevel_dir = options.depth
379
372380 # -D on the command line sets variable defaults - D isn't just for define,
373381 # it's for default. Perhaps there should be a way to force (-F?) a
374382 # variable's value so that it can't be overridden by anything else.
220220
221221
222222 def DeepDependencyTargets(target_dicts, roots):
223 """Returns the recursive list of target dependencies.
224 """
223 """Returns the recursive list of target dependencies."""
225224 dependencies = set()
226 for r in roots:
225 pending = set(roots)
226 while pending:
227 # Pluck out one.
228 r = pending.pop()
229 # Skip if visited already.
230 if r in dependencies:
231 continue
232 # Add it.
233 dependencies.add(r)
234 # Add its children.
227235 spec = target_dicts[r]
228 r_deps = list(set((spec.get('dependencies', []) +
229 spec.get('dependencies_original', []))))
230 for d in r_deps:
231 if d not in roots:
232 dependencies.add(d)
233 for d in DeepDependencyTargets(target_dicts, r_deps):
234 if d not in roots:
235 dependencies.add(d)
236 return list(dependencies)
236 pending.update(set(spec.get('dependencies', [])))
237 pending.update(set(spec.get('dependencies_original', [])))
238 return list(dependencies - set(roots))
237239
238240
239241 def BuildFileTargets(target_list, build_file):
0 #!/usr/bin/python
1
2 # Copyright (c) 2011 Google Inc. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 import xml.dom
7 import xml_fix
8 import common
9
10 class EasyXml(object):
11 """ Class to easily create XML files with substantial pre-defined structures.
12
13 Visual Studio files have a lot of pre-defined structures. This class makes
14 it easy to represent these structures as Python data structures, instead of
15 having to create a lot of function calls.
16
17 For this class, an XML element is represented as a list composed of:
18 1. The name of the element, a string,
19 2. The attributes of the element, an dictionary (optional), and
20 3+. The content of the element, if any. Strings are simple text nodes and
21 lists are child elements.
22
23 Example 1:
24 <test/>
25 becomes
26 ['test']
27
28 Example 2:
29 <myelement a='value1' b='value2'>
30 <childtype>This is</childtype>
31 <childtype>it!</childtype>
32 </myelement>
33
34 becomes
35 ['myelement', {'a':'value1', 'b':'value2'},
36 ['childtype', 'This is'],
37 ['childtype', 'it!'],
38 ]
39 """
40
41 def __init__(self, name, attributes=None):
42 """ Constructs an object representing an XML document.
43
44 Args:
45 name: A string, the name of the root element.
46 attributes: A dictionary, the attributes of the root.
47 """
48 xml_impl = xml.dom.getDOMImplementation()
49 self.doc = xml_impl.createDocument(None, name, None)
50 if attributes:
51 self.SetAttributes(self.doc.documentElement, attributes)
52
53 def AppendChildren(self, parent, children_specifications):
54 """ Appends multiple children.
55
56 Args:
57 parent: The node to which the children will be added.
58 children_specifications: A list of node specifications.
59 """
60 for specification in children_specifications:
61 # If it's a string, append a text node.
62 # Otherwise append an XML node.
63 if isinstance(specification, str):
64 parent.appendChild(self.doc.createTextNode(specification))
65 else:
66 self.AppendNode(parent, specification)
67
68 def AppendNode(self, parent, specification):
69 """ Appends multiple children.
70
71 Args:
72 parent: The node to which the child will be added.
73 children_specifications: A list, the node specification. The first
74 entry is the name of the element. If the second entry is a
75 dictionary, it is the attributes. The remaining entries of the
76 list are the sub-elements.
77 Returns:
78 The XML element created.
79 """
80 name = specification[0]
81 if not isinstance(name, str):
82 raise Exception('The first item of an EasyXml specification should be '
83 'a string. Specification was ' + str(specification))
84 element = self.doc.createElement(name)
85 parent.appendChild(element)
86 rest = specification[1:]
87 # The second element is optionally a dictionary of the attributes.
88 if rest and isinstance(rest[0], dict):
89 self.SetAttributes(element, rest[0])
90 rest = rest[1:]
91 if rest:
92 self.AppendChildren(element, rest)
93 return element
94
95 def SetAttributes(self, element, attribute_description):
96 """ Sets the attributes of an element.
97
98 Args:
99 element: The node to which the child will be added.
100 attribute_description: A dictionary that maps attribute names to
101 attribute values.
102 """
103 for attribute, value in attribute_description.iteritems():
104 element.setAttribute(attribute, value)
105
106 def Root(self):
107 """ Returns the root element. """
108 return self.doc.documentElement
109
110 def WriteIfChanged(self, path):
111 """ Writes the XML doc but don't touch the file if unchanged. """
112 f = common.WriteOnDiff(path)
113 fix = xml_fix.XmlFix()
114 self.doc.writexml(f, encoding='utf-8', addindent='', newl='')
115 fix.Cleanup()
116 f.close()
117
118 def __str__(self):
119 """ Converts the doc to a string. """
120 return self.doc.toxml()
0 #!/usr/bin/python
1
2 # Copyright (c) 2011 Google Inc. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 """ Unit tests for the easy_xml.py file. """
7
8 import easy_xml
9 import unittest
10 import StringIO
11
12
13 class TestSequenceFunctions(unittest.TestCase):
14
15 def setUp(self):
16 self.stderr = StringIO.StringIO()
17
18 def test_EasyXml_simple(self):
19 xml = easy_xml.EasyXml('test')
20 self.assertEqual(str(xml), '<?xml version="1.0" ?><test/>')
21
22 def test_EasyXml_simple_with_attributes(self):
23 xml = easy_xml.EasyXml('test2', {'a': 'value1', 'b': 'value2'})
24 self.assertEqual(str(xml),
25 '<?xml version="1.0" ?><test2 a="value1" b="value2"/>')
26
27 def test_EasyXml_add_node(self):
28 # We want to create:
29 target = ('<?xml version="1.0" ?>'
30 '<test3>'
31 '<GrandParent>'
32 '<Parent1>'
33 '<Child/>'
34 '</Parent1>'
35 '<Parent2/>'
36 '</GrandParent>'
37 '</test3>')
38
39 # Do it the hard way first:
40 xml = easy_xml.EasyXml('test3')
41 grand_parent = xml.AppendNode(xml.Root(), ['GrandParent'])
42 parent1 = xml.AppendNode(grand_parent, ['Parent1'])
43 parent2 = xml.AppendNode(grand_parent, ['Parent2'])
44 xml.AppendNode(parent1, ['Child'])
45 self.assertEqual(str(xml), target)
46
47 # Do it the easier way:
48 xml = easy_xml.EasyXml('test3')
49 xml.AppendNode(xml.Root(),
50 ['GrandParent',
51 ['Parent1', ['Child']],
52 ['Parent2']])
53 self.assertEqual(str(xml), target)
54
55 def test_EasyXml_complex(self):
56 # We want to create:
57 target = ('<?xml version="1.0" ?>'
58 '<Project>'
59 '<PropertyGroup Label="Globals">'
60 '<ProjectGuid>{D2250C20-3A94-4FB9-AF73-11BC5B73884B}</ProjectGuid>'
61 '<Keyword>Win32Proj</Keyword>'
62 '<RootNamespace>automated_ui_tests</RootNamespace>'
63 '</PropertyGroup>'
64 '<Import Project="$(VCTargetsPath)\\Microsoft.Cpp.props"/>'
65 '<PropertyGroup Condition="\'$(Configuration)|$(Platform)\'==\''
66 'Debug|Win32\'" Label="Configuration">'
67 '<ConfigurationType>Application</ConfigurationType>'
68 '<CharacterSet>Unicode</CharacterSet>'
69 '</PropertyGroup>'
70 '</Project>')
71
72 xml = easy_xml.EasyXml('Project')
73 xml.AppendChildren(xml.Root(), [
74 ['PropertyGroup', {'Label': 'Globals'},
75 ['ProjectGuid', '{D2250C20-3A94-4FB9-AF73-11BC5B73884B}'],
76 ['Keyword', 'Win32Proj'],
77 ['RootNamespace', 'automated_ui_tests']
78 ],
79 ['Import', {'Project': '$(VCTargetsPath)\\Microsoft.Cpp.props'}],
80 ['PropertyGroup',
81 {'Condition': "'$(Configuration)|$(Platform)'=='Debug|Win32'",
82 'Label': 'Configuration'},
83 ['ConfigurationType', 'Application'],
84 ['CharacterSet', 'Unicode']
85 ]
86 ])
87 self.assertEqual(str(xml), target)
88
89
90 if __name__ == '__main__':
91 unittest.main()
00 #!/usr/bin/python
11
2 # Copyright (c) 2009 Google Inc. All rights reserved.
2 # Copyright (c) 2011 Google Inc. All rights reserved.
33 # Use of this source code is governed by a BSD-style license that can be
44 # found in the LICENSE file.
55
2424
2525 import gyp
2626 import gyp.common
27 import gyp.system_test
2728 import os.path
29 import os
2830
2931 # Debugging-related imports -- remove me once we're solid.
3032 import code
7173 # It's even quicker (saves ~200ms) to pass -r on the command line.
7274 MAKEFLAGS=-r
7375
76 # The source directory tree.
77 srcdir := %(srcdir)s
78
79 # The name of the builddir.
80 builddir_name ?= %(builddir)s
81
7482 # The V=1 flag on command line makes us verbosely print command lines.
7583 ifdef V
7684 quiet=
7987 endif
8088
8189 # Specify BUILDTYPE=Release on the command line for a release build.
82 BUILDTYPE ?= __default_configuration__
90 BUILDTYPE ?= %(default_configuration)s
8391
8492 # Directory all our build output goes into.
8593 # Note that this must be two directories beneath src/ for unit tests to pass,
97105 all_deps :=
98106
99107 # C++ apps need to be linked with g++. Not sure what's appropriate.
100 LINK ?= $(CXX)
108 #
109 # Note, the flock is used to seralize linking. Linking is a memory-intensive
110 # process so running parallel links can often lead to thrashing. To disable
111 # the serialization, override LINK via an envrionment variable as follows:
112 #
113 # export LINK="$(CXX)"
114 #
115 # This will allow make to invoke N linker processes as specified in -jN.
116 LINK ?= flock $(builddir)/linker.lock $(CXX) %(LINK_flags)s
101117
102118 CC.target ?= $(CC)
103119 CFLAGS.target ?= $(CFLAGS)
106122 LINK.target ?= $(LINK)
107123 LDFLAGS.target ?= $(LDFLAGS)
108124 AR.target ?= $(AR)
109 RANLIB.target ?= ranlib
110
125 ARFLAGS.target ?= %(ARFLAGS.target)s
126
127 # N.B.: the logic of which commands to run should match the computation done
128 # in gyp's make.py where ARFLAGS.host etc. is computed.
129 # TODO(evan): move all cross-compilation logic to gyp-time so we don't need
130 # to replicate this environment fallback in make as well.
111131 CC.host ?= gcc
112132 CFLAGS.host ?=
113133 CXX.host ?= g++
115135 LINK.host ?= g++
116136 LDFLAGS.host ?=
117137 AR.host ?= ar
118 RANLIB.host ?= ranlib
138 ARFLAGS.host := %(ARFLAGS.host)s
119139
120140 # Flags to make gcc output dependency info. Note that you need to be
121141 # careful here to use the flags that ccache and distcc can understand.
144164 # and dollar signs past make, the shell, and sed at the same time."""
145165 r"""
146166 define fixup_dep
167 # The depfile may not exist if the input file didn't have any #includes.
168 touch $(depfile).raw
147169 # Fixup path as in (1).
148170 sed -e "s|^$(notdir $@)|$@|" $(depfile).raw >> $(depfile)
149171 # Add extra rules as in (2).
150172 # We remove slashes and replace spaces with new lines;
151173 # remove blank lines;
152174 # delete the first line and append a colon to the remaining lines.
153 sed -e 's|\\||' -e 's| |\n|g' $(depfile).raw |\
154 grep -v '^$$' |\
155 sed -e 1d -e 's|$$|:|' \
175 sed -e 's|\\||' -e 'y| |\n|' $(depfile).raw |\
176 grep -v '^$$' |\
177 sed -e 1d -e 's|$$|:|' \
156178 >> $(depfile)
157179 rm $(depfile).raw
158180 endef
163185 # - quiet_cmd_foo is the brief-output summary of the command.
164186
165187 quiet_cmd_cc = CC($(TOOLSET)) $@
166 cmd_cc = $(CC.$(TOOLSET)) $(CFLAGS.$(TOOLSET)) $(GYP_CFLAGS) $(DEPFLAGS) -c -o $@ $<
188 cmd_cc = $(CC.$(TOOLSET)) $(GYP_CFLAGS) $(DEPFLAGS) $(CFLAGS.$(TOOLSET)) -c -o $@ $<
167189
168190 quiet_cmd_cxx = CXX($(TOOLSET)) $@
169 cmd_cxx = $(CXX.$(TOOLSET)) $(CXXFLAGS.$(TOOLSET)) $(GYP_CXXFLAGS) $(DEPFLAGS) -c -o $@ $<
170
171 quiet_cmd_alink = AR+RANLIB($(TOOLSET)) $@
172 cmd_alink = rm -f $@ && $(AR.$(TOOLSET)) rc $@ $(filter %.o,$^) && $(RANLIB.$(TOOLSET)) $@
191 cmd_cxx = $(CXX.$(TOOLSET)) $(GYP_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $<
192
193 quiet_cmd_alink = AR($(TOOLSET)) $@
194 cmd_alink = rm -f $@ && $(AR.$(TOOLSET)) $(ARFLAGS.$(TOOLSET)) $@ $(filter %%.o,$^)
173195
174196 quiet_cmd_touch = TOUCH $@
175197 cmd_touch = touch $@
182204 # special "figure out circular dependencies" flags around the entire
183205 # input list during linking.
184206 quiet_cmd_link = LINK($(TOOLSET)) $@
185 cmd_link = $(LINK.$(TOOLSET)) $(LDFLAGS.$(TOOLSET)) $(GYP_LDFLAGS) -o $@ -Wl,--start-group $(filter-out FORCE_DO_CMD, $^) -Wl,--end-group $(LIBS)
207 cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ -Wl,--start-group $(filter-out FORCE_DO_CMD, $^) -Wl,--end-group $(LIBS)
186208
187209 # Shared-object link (for generating .so).
188210 # Set SONAME to the library filename so our binaries don't reference the local,
189211 # absolute paths used on the link command-line.
190212 # TODO: perhaps this can share with the LINK command above?
191213 quiet_cmd_solink = SOLINK($(TOOLSET)) $@
192 cmd_solink = $(LINK.$(TOOLSET)) -shared $(LDFLAGS.$(TOOLSET)) $(GYP_LDFLAGS) -Wl,-soname=$(@F) -o $@ -Wl,--start-group $(filter-out FORCE_DO_CMD, $^) -Wl,--end-group $(LIBS)
214 cmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--start-group $(filter-out FORCE_DO_CMD, $^) -Wl,--end-group $(LIBS)
193215 """
194216 r"""
195217 # Define an escape_quotes function to escape single quotes.
205227 # make. This uses printf instead of echo because printf's behaviour with respect
206228 # to escape sequences is more portable than echo's across different shells
207229 # (e.g., dash, bash).
208 exact_echo = printf '%s\n' '$(call escape_quotes,$(1))'
230 exact_echo = printf '%%s\n' '$(call escape_quotes,$(1))'
209231 """
210232 """
211233 # Helper to compare the command we're about to run against the command
230252
231253 # do_cmd: run a command via the above cmd_foo names, if necessary.
232254 # Should always run for a given target to handle command-line changes.
233 # Second argument, if non-zero, makes it do C/C++ dependency munging.
255 # Second argument, if non-zero, makes it do asm/C/C++ dependency munging.
234256 define do_cmd
235257 $(if $(or $(command_changed),$(prereq_changed)),
236258 @$(call exact_echo, $($(quiet)cmd_$(1)))
237259 @mkdir -p $(dir $@) $(dir $(depfile))
238 @$(cmd_$(1))
260 $(if $(findstring flock,$(word 1,$(cmd_$1))),
261 @$(cmd_$(1))
262 @echo " $(quiet_cmd_$(1)): Finished",
263 @$(cmd_$(1))
264 )
239265 @$(call exact_echo,$(call escape_vars,cmd_$@ := $(cmd_$(1)))) > $(depfile)
240266 @$(if $(2),$(fixup_dep))
241267 )
245271 # deps yet.
246272 .PHONY: all
247273 all:
248
249 # make looks for ways to re-generate included makefiles, but in our case, we
250 # don't have a direct way. Explicitly telling make that it has nothing to do
251 # for them makes it go faster.
252 %.d: ;
253274
254275 # Use FORCE_DO_CMD to force a target to run. Should be coupled with
255276 # do_cmd.
263284 $(obj).$(TOOLSET)/%.o: $(srcdir)/%.c FORCE_DO_CMD
264285 @$(call do_cmd,cc,1)
265286 $(obj).$(TOOLSET)/%.o: $(srcdir)/%.s FORCE_DO_CMD
266 @$(call do_cmd,cc)
287 @$(call do_cmd,cc,1)
267288 $(obj).$(TOOLSET)/%.o: $(srcdir)/%.S FORCE_DO_CMD
268 @$(call do_cmd,cc)
289 @$(call do_cmd,cc,1)
269290 $(obj).$(TOOLSET)/%.o: $(srcdir)/%.cpp FORCE_DO_CMD
270291 @$(call do_cmd,cxx,1)
271292 $(obj).$(TOOLSET)/%.o: $(srcdir)/%.cc FORCE_DO_CMD
277298 $(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.c FORCE_DO_CMD
278299 @$(call do_cmd,cc,1)
279300 $(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.s FORCE_DO_CMD
280 @$(call do_cmd,cc)
301 @$(call do_cmd,cc,1)
281302 $(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.S FORCE_DO_CMD
282 @$(call do_cmd,cc)
303 @$(call do_cmd,cc,1)
283304 $(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cc FORCE_DO_CMD
284305 @$(call do_cmd,cxx,1)
285306 $(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cpp FORCE_DO_CMD
290311 $(obj).$(TOOLSET)/%.o: $(obj)/%.c FORCE_DO_CMD
291312 @$(call do_cmd,cc,1)
292313 $(obj).$(TOOLSET)/%.o: $(obj)/%.s FORCE_DO_CMD
293 @$(call do_cmd,cc)
314 @$(call do_cmd,cc,1)
294315 $(obj).$(TOOLSET)/%.o: $(obj)/%.S FORCE_DO_CMD
295 @$(call do_cmd,cc)
316 @$(call do_cmd,cc,1)
296317 $(obj).$(TOOLSET)/%.o: $(obj)/%.cc FORCE_DO_CMD
297318 @$(call do_cmd,cxx,1)
298319 $(obj).$(TOOLSET)/%.o: $(obj)/%.cpp FORCE_DO_CMD
312333 """),
313334 '.s': ("""\
314335 $(obj).$(TOOLSET)/$(TARGET)/%.o: $(srcdir)/%.s FORCE_DO_CMD
315 @$(call do_cmd,cc)
336 @$(call do_cmd,cc,1)
316337 """),
317338 '.S': ("""\
318339 $(obj).$(TOOLSET)/$(TARGET)/%.o: $(srcdir)/%.S FORCE_DO_CMD
319 @$(call do_cmd,cc)
340 @$(call do_cmd,cc,1)
320341 """),
321342 '.cpp': ("""\
322343 $(obj).$(TOOLSET)/$(TARGET)/%.o: $(srcdir)/%.cpp FORCE_DO_CMD
374395 ''.join(SHARED_HEADER_SUFFIX_RULES_OBJDIR2.values())
375396 )
376397
377 # This gets added to the very beginning of the Makefile.
378 SHARED_HEADER_SRCDIR = ("""\
379 # The source directory tree.
380 srcdir := %s
381
382 """)
383
384 SHARED_HEADER_BUILDDIR_NAME = ("""\
385 # The name of the builddir.
386 builddir_name ?= %s
387
388 """)
389
390398 SHARED_FOOTER = """\
391399 # "all" is a concatenation of the "all" targets from all the included
392400 # sub-makefiles. This is just here to clarify.
399407 # Of those, only consider the ones with .d (dependency) info:
400408 d_files := $(wildcard $(foreach f,$(all_deps),$(depsdir)/$(f).d))
401409 ifneq ($(d_files),)
402 include $(d_files)
410 # Rather than include each individual .d file, concatenate them into a
411 # single file which make is able to load faster. We split this into
412 # commands that take 1000 files at a time to avoid overflowing the
413 # command line.
414 $(shell cat $(wordlist 1,1000,$(d_files)) > $(depsdir)/all.deps)
415 %(generate_all_deps)s
416 # make looks for ways to re-generate included makefiles, but in our case, we
417 # don't have a direct way. Explicitly telling make that it has nothing to do
418 # for them makes it go faster.
419 $(depsdir)/all.deps: ;
420
421 include $(depsdir)/all.deps
403422 endif
404423 """
405424
418437 return False
419438
420439
440 def Linkable(filename):
441 """Return true if the file is linkable (should be on the link line)."""
442 return filename.endswith('.o')
443
444
421445 def Target(filename):
422446 """Translate a compilable filename to its .o target."""
423447 return os.path.splitext(filename)[0] + '.o'
450474 if '"' in string:
451475 string = '"' + string.replace('"', '\\"') + '"'
452476 return string
477
478
479 def StringToMakefileVariable(string):
480 """Convert a string to a value that is acceptable as a make variable name."""
481 # TODO: replace other metacharacters that we encounter.
482 return string.replace(' ', '_')
453483
454484
455485 srcdir_prefix = ''
476506 Its only real entry point is Write(), and is mostly used for namespacing.
477507 """
478508
509 def __init__(self):
510 # Keep track of the total number of outputs for this makefile.
511 self._num_outputs = 0
512
513
514 def NumOutputs(self):
515 return self._num_outputs
516
517
479518 def Write(self, qualified_target, base_path, output_filename, spec, configs,
480519 part_of_all):
481520 """The main entry point: writes a .mk file for a single target.
488527 spec, configs: gyp info
489528 part_of_all: flag indicating this target is part of 'all'
490529 """
491 print 'Generating %s' % output_filename
492
493530 ensure_directory_exists(output_filename)
494531
495532 self.fp = open(output_filename, 'w')
515552 'shared_library')
516553 if self.type in self._INSTALLABLE_TARGETS:
517554 self.alias = os.path.basename(self.output)
555 install_path = self._InstallableTargetInstallPath()
518556 else:
519557 self.alias = self.output
558 install_path = self.output
520559
521560 self.WriteLn("TOOLSET := " + self.toolset)
522561 self.WriteLn("TARGET := " + self.target)
558597 extra_link_deps + link_deps, extra_outputs, part_of_all)
559598
560599 # Update global list of target outputs, used in dependency tracking.
561 target_outputs[qualified_target] = self.alias
600 target_outputs[qualified_target] = install_path
562601
563602 # Update global list of link dependencies.
564603 if self.type == 'static_library':
583622 targets: list of "all" targets for this sub-project
584623 build_dir: build output directory, relative to the sub-project
585624 """
586 print 'Generating %s' % output_filename
587
588625 ensure_directory_exists(output_filename)
589626 self.fp = open(output_filename, 'w')
590627 self.fp.write(header)
611648 part_of_all: flag indicating this target is part of 'all'
612649 """
613650 for action in actions:
614 name = self.target + '_' + action['action_name']
651 name = self.target + '_' + StringToMakefileVariable(action['action_name'])
615652 self.WriteLn('### Rules for action "%s":' % action['action_name'])
616653 inputs = action['inputs']
617654 outputs = action['outputs']
680717 part_of_all: flag indicating this target is part of 'all'
681718 """
682719 for rule in rules:
683 name = self.target + '_' + rule['rule_name']
720 name = self.target + '_' + StringToMakefileVariable(rule['rule_name'])
684721 count = 0
685722 self.WriteLn('### Generated for rule %s:' % name)
686723
687724 all_outputs = []
688725
689 for rule_source in rule['rule_sources']:
726 for rule_source in rule.get('rule_sources', []):
690727 dirs = set()
691728 rule_source_basename = os.path.basename(rule_source)
692729 (rule_source_root, rule_source_ext) = \
721758 self.WriteMakeRule(outputs[:1], ['builddir := $(abs_builddir)'])
722759 self.WriteMakeRule(outputs, inputs + ['FORCE_DO_CMD'], actions)
723760 self.WriteLn('all_deps += %s' % ' '.join(outputs))
761 self._num_outputs += len(outputs)
724762
725763 action = [self.ExpandInputRoot(ac, rule_source_root)
726764 for ac in rule['action']]
819857 includes = map(Sourceify, map(self.Absolutify, includes))
820858 self.WriteList(includes, 'INCS_%s' % configname, prefix='-I')
821859
822 sources = filter(Compilable, sources)
823 objs = map(self.Objectify, map(self.Absolutify, map(Target, sources)))
860 compilable = filter(Compilable, sources)
861 objs = map(self.Objectify, map(self.Absolutify, map(Target, compilable)))
824862 self.WriteList(objs, 'OBJS')
825863
826864 self.WriteLn('# Add to the list of files we specially track '
827865 'dependencies for.')
828866 self.WriteLn('all_deps += $(OBJS)')
867 self._num_outputs += len(objs)
829868 self.WriteLn()
830869
831870 # Make sure our dependencies are built first.
850889 # CFLAGS et al overrides must be target-local.
851890 # See "Target-specific Variable Values" in the GNU Make manual.""")
852891 self.WriteLn("$(OBJS): TOOLSET := $(TOOLSET)")
853 self.WriteLn("$(OBJS): GYP_CFLAGS := $(CFLAGS_$(BUILDTYPE)) "
854 "$(CFLAGS_C_$(BUILDTYPE)) "
855 "$(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))")
856 self.WriteLn("$(OBJS): GYP_CXXFLAGS := $(CFLAGS_$(BUILDTYPE)) "
857 "$(CFLAGS_CC_$(BUILDTYPE)) "
858 "$(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))")
892 self.WriteLn("$(OBJS): GYP_CFLAGS := "
893 "$(DEFS_$(BUILDTYPE)) "
894 "$(INCS_$(BUILDTYPE)) "
895 "$(CFLAGS_$(BUILDTYPE)) "
896 "$(CFLAGS_C_$(BUILDTYPE))")
897 self.WriteLn("$(OBJS): GYP_CXXFLAGS := "
898 "$(DEFS_$(BUILDTYPE)) "
899 "$(INCS_$(BUILDTYPE)) "
900 "$(CFLAGS_$(BUILDTYPE)) "
901 "$(CFLAGS_CC_$(BUILDTYPE))")
902
903 # If there are any object files in our input file list, link them into our
904 # output.
905 extra_link_deps += filter(Linkable, sources)
859906
860907 self.WriteLn()
861908
9881035 # 2) They get shortcuts for building (e.g. "make chrome").
9891036 # 3) They are part of "make all".
9901037 if self.type in self._INSTALLABLE_TARGETS:
991 if self.type in ('shared_library'):
1038 if self.type == 'shared_library':
9921039 file_desc = 'shared library'
993 # Install all shared libs into a common directory (per toolset) for
994 # convenient access with LD_LIBRARY_PATH.
995 binpath = '$(builddir)/lib.%s/%s' % (self.toolset, self.alias)
9961040 else:
9971041 file_desc = 'executable'
998 binpath = '$(builddir)/' + self.alias
1042 install_path = self._InstallableTargetInstallPath()
9991043 installable_deps = [self.output]
10001044 # Point the target alias to the final binary output.
1001 self.WriteMakeRule([self.target], [binpath],
1045 self.WriteMakeRule([self.target], [install_path],
10021046 comment='Add target alias', phony = True)
1003 if binpath != self.output:
1004 self.WriteDoCmd([binpath], [self.output], 'copy',
1047 if install_path != self.output:
1048 self.WriteDoCmd([install_path], [self.output], 'copy',
10051049 comment = 'Copy this to the %s output path.' %
10061050 file_desc, part_of_all=part_of_all)
1007 installable_deps.append(binpath)
1051 installable_deps.append(install_path)
10081052 if self.output != self.alias and self.alias != self.target:
10091053 self.WriteMakeRule([self.alias], installable_deps,
10101054 comment = 'Short alias for building this %s.' %
10111055 file_desc, phony = True)
10121056 if part_of_all:
1013 self.WriteMakeRule(['all'], [binpath],
1057 self.WriteMakeRule(['all'], [install_path],
10141058 comment = 'Add %s to "all" target.' % file_desc,
10151059 phony = True)
10161060
10411085 force = True)
10421086 # Add our outputs to the list of targets we read depfiles from.
10431087 self.WriteLn('all_deps += %s' % ' '.join(outputs))
1088 self._num_outputs += len(outputs)
10441089
10451090
10461091 def WriteMakeRule(self, outputs, inputs, actions=None, comment=None,
11401185 return path
11411186
11421187
1188 def _InstallableTargetInstallPath(self):
1189 """Returns the location of the final output for an installable target."""
1190 if self.type == 'shared_library':
1191 # Install all shared libs into a common directory (per toolset) for
1192 # convenient access with LD_LIBRARY_PATH.
1193 return '$(builddir)/lib.%s/%s' % (self.toolset, self.alias)
1194 return '$(builddir)/' + self.alias
1195
1196
1197 def WriteAutoRegenerationRule(params, root_makefile, makefile_name,
1198 build_files):
1199 """Write the target to regenerate the Makefile."""
1200 options = params['options']
1201 build_files_args = [gyp.common.RelativePath(filename, options.toplevel_dir)
1202 for filename in params['build_files_arg']]
1203 gyp_binary = gyp.common.FixIfRelativePath(params['gyp_binary'],
1204 options.toplevel_dir)
1205 if not gyp_binary.startswith(os.sep):
1206 gyp_binary = os.path.join('.', gyp_binary)
1207 root_makefile.write(
1208 "quiet_cmd_regen_makefile = ACTION Regenerating $@\n"
1209 "cmd_regen_makefile = %(cmd)s\n"
1210 "%(makefile_name)s: %(deps)s\n"
1211 "\t$(call do_cmd,regen_makefile)\n\n" % {
1212 'makefile_name': makefile_name,
1213 'deps': ' '.join(map(Sourceify, build_files)),
1214 'cmd': gyp.common.EncodePOSIXShellList(
1215 [gyp_binary, '-fmake'] +
1216 gyp.RegenerateFlags(options) +
1217 build_files_args)})
1218
1219
1220 def RunSystemTests():
1221 """Run tests against the system to compute default settings for commands.
1222
1223 Returns:
1224 dictionary of settings matching the block of command-lines used in
1225 SHARED_HEADER. E.g. the dictionary will contain a ARFLAGS.target
1226 key for the default ARFLAGS for the target ar command.
1227 """
1228 # Compute flags used for building static archives.
1229 # N.B.: this fallback logic should match the logic in SHARED_HEADER.
1230 # See comment there for more details.
1231 ar_target = os.environ.get('AR.target', os.environ.get('AR', 'ar'))
1232 cc_target = os.environ.get('CC.target', os.environ.get('CC', 'cc'))
1233 arflags_target = 'crs'
1234 if gyp.system_test.TestArSupportsT(ar_command=ar_target,
1235 cc_command=cc_target):
1236 arflags_target = 'crsT'
1237
1238 ar_host = os.environ.get('AR.host', 'ar')
1239 cc_host = os.environ.get('CC.host', 'gcc')
1240 arflags_host = 'crs'
1241 # It feels redundant to compute this again given that most builds aren't
1242 # cross-compiles, but due to quirks of history CC.host defaults to 'gcc'
1243 # while CC.target defaults to 'cc', so the commands really are different
1244 # even though they're nearly guaranteed to run the same code underneath.
1245 if gyp.system_test.TestArSupportsT(ar_command=ar_host, cc_command=cc_host):
1246 arflags_host = 'crsT'
1247
1248 link_flags = ''
1249 if gyp.system_test.TestLinkerSupportsThreads(cc_command=cc_target):
1250 # N.B. we don't test for cross-compilation; as currently written, we
1251 # don't even use flock when linking in the cross-compile setup!
1252 # TODO(evan): refactor cross-compilation such that this code can
1253 # be reused.
1254 link_flags = '-Wl,--threads -Wl,--thread-count=4'
1255
1256 # TODO(evan): cache this output. (But then we'll need to add extra
1257 # flags to gyp to flush the cache, yuk! It's fast enough for now to
1258 # just run it every time.)
1259
1260 return { 'ARFLAGS.target': arflags_target,
1261 'ARFLAGS.host': arflags_host,
1262 'LINK_flags': link_flags }
1263
1264
1265 def CalculateVariables(default_variables, params):
1266 """Calculate additional variables for use in the build (called by gyp)."""
1267 cc_target = os.environ.get('CC.target', os.environ.get('CC', 'cc'))
1268 default_variables['LINKER_SUPPORTS_ICF'] = \
1269 gyp.system_test.TestLinkerSupportsICF(cc_command=cc_target)
1270
1271
11431272 def GenerateOutput(target_list, target_dicts, data, params):
11441273 options = params['options']
11451274 generator_flags = params.get('generator_flags', {})
11571286 output_file = os.path.join(options.depth, base_path, base_name)
11581287 if options.generator_output:
11591288 output_file = os.path.join(options.generator_output, output_file)
1160 return (base_path, output_file)
1289 base_path = gyp.common.RelativePath(os.path.dirname(build_file),
1290 options.toplevel_dir)
1291 return base_path, output_file
11611292
11621293 # TODO: search for the first non-'Default' target. This can go
11631294 # away when we add verification that all targets have the
11741305
11751306 srcdir = '.'
11761307 makefile_name = 'Makefile' + options.suffix
1177 makefile_path = os.path.join(options.depth, makefile_name)
1308 makefile_path = os.path.join(options.toplevel_dir, makefile_name)
11781309 if options.generator_output:
11791310 global srcdir_prefix
11801311 makefile_path = os.path.join(options.generator_output, makefile_path)
11811312 srcdir = gyp.common.RelativePath(srcdir, options.generator_output)
11821313 srcdir_prefix = '$(srcdir)/'
1314
1315 header_params = {
1316 'srcdir': srcdir,
1317 'builddir': builddir_name,
1318 'default_configuration': default_configuration,
1319 }
1320 header_params.update(RunSystemTests())
1321
11831322 ensure_directory_exists(makefile_path)
11841323 root_makefile = open(makefile_path, 'w')
1185 root_makefile.write(SHARED_HEADER_SRCDIR % srcdir)
1186 root_makefile.write(SHARED_HEADER_BUILDDIR_NAME % builddir_name)
1187 root_makefile.write(SHARED_HEADER.replace('__default_configuration__',
1188 default_configuration))
1324 root_makefile.write(SHARED_HEADER % header_params)
11891325 for toolset in toolsets:
11901326 root_makefile.write('TOOLSET := %s\n' % toolset)
11911327 root_makefile.write(ROOT_HEADER_SUFFIX_RULES)
11961332 for target in gyp.common.AllTargets(target_list, target_dicts, build_file):
11971333 needed_targets.add(target)
11981334
1335 num_outputs = 0
11991336 build_files = set()
12001337 include_list = set()
12011338 for qualified_target in target_list:
12021339 build_file, target, toolset = gyp.common.ParseQualifiedTarget(
12031340 qualified_target)
1204 build_files.add(gyp.common.RelativePath(build_file, options.depth))
1341 build_files.add(gyp.common.RelativePath(build_file, options.toplevel_dir))
12051342 included_files = data[build_file]['included_files']
12061343 for included_file in included_files:
12071344 # The included_files entries are relative to the dir of the build file
12081345 # that included them, so we have to undo that and then make them relative
12091346 # to the root dir.
12101347 relative_include_file = gyp.common.RelativePath(
1211 gyp.common.UnrelativePath(included_file, build_file), options.depth)
1348 gyp.common.UnrelativePath(included_file, build_file),
1349 options.toplevel_dir)
12121350 abs_include_file = os.path.abspath(relative_include_file)
12131351 # If the include file is from the ~/.gyp dir, we should use absolute path
12141352 # so that relocating the src dir doesn't break the path.
12181356 else:
12191357 build_files.add(relative_include_file)
12201358
1221 (base_path, output_file) = CalculateMakefilePath(build_file,
1359 base_path, output_file = CalculateMakefilePath(build_file,
12221360 target + '.' + toolset + options.suffix + '.mk')
12231361
12241362 spec = target_dicts[qualified_target]
12271365 writer = MakefileWriter()
12281366 writer.Write(qualified_target, base_path, output_file, spec, configs,
12291367 part_of_all=qualified_target in needed_targets)
1368 num_outputs += writer.NumOutputs()
12301369
12311370 # Our root_makefile lives at the source root. Compute the relative path
12321371 # from there to the output_file for including.
12331372 mkfile_rel_path = gyp.common.RelativePath(output_file,
12341373 os.path.dirname(makefile_path))
1235 include_list.add('include ' + mkfile_rel_path + '\n')
1374 include_list.add(mkfile_rel_path)
12361375
12371376 # Write out per-gyp (sub-project) Makefiles.
12381377 depth_rel_path = gyp.common.RelativePath(options.depth, os.getcwd())
12471386 # Only generate Makefiles for gyp files with targets.
12481387 if not gyp_targets:
12491388 continue
1250 (base_path, output_file) = CalculateMakefilePath(build_file,
1389 base_path, output_file = CalculateMakefilePath(build_file,
12511390 os.path.splitext(os.path.basename(build_file))[0] + '.Makefile')
12521391 makefile_rel_path = gyp.common.RelativePath(os.path.dirname(makefile_path),
12531392 os.path.dirname(output_file))
12571396
12581397 # Write out the sorted list of includes.
12591398 root_makefile.write('\n')
1260 for include in sorted(include_list):
1261 root_makefile.write(include)
1399 for include_file in sorted(include_list):
1400 # We wrap each .mk include in an if statement so users can tell make to
1401 # not load a file by setting NO_LOAD. The below make code says, only
1402 # load the .mk file if the .mk filename doesn't start with a token in
1403 # NO_LOAD.
1404 root_makefile.write(
1405 "ifeq ($(strip $(foreach prefix,$(NO_LOAD),\\\n"
1406 " $(findstring $(join ^,$(prefix)),\\\n"
1407 " $(join ^," + include_file + ")))),)\n")
1408 root_makefile.write(" include " + include_file + "\n")
1409 root_makefile.write("endif\n")
12621410 root_makefile.write('\n')
12631411
1264 # Write the target to regenerate the Makefile.
12651412 if generator_flags.get('auto_regeneration', True):
1266 build_files_args = [gyp.common.RelativePath(filename, options.depth)
1267 for filename in params['build_files_arg']]
1268 gyp_binary = gyp.common.FixIfRelativePath(params['gyp_binary'],
1269 options.depth)
1270 if not gyp_binary.startswith(os.sep):
1271 gyp_binary = os.path.join('.', gyp_binary)
1272 root_makefile.write("%s: %s\n\t%s\n" % (
1273 makefile_name,
1274 ' '.join(map(Sourceify, build_files)),
1275 gyp.common.EncodePOSIXShellList(
1276 [gyp_binary, '-fmake'] +
1277 gyp.RegenerateFlags(options) +
1278 build_files_args)))
1279
1280 root_makefile.write(SHARED_FOOTER)
1413 WriteAutoRegenerationRule(params, root_makefile, makefile_name, build_files)
1414
1415 # Write the rule to load dependencies. We batch 1000 files at a time to
1416 # avoid overflowing the command line.
1417 all_deps = ""
1418 for i in range(1001, num_outputs, 1000):
1419 all_deps += ("""
1420 ifneq ($(word %(start)d,$(d_files)),)
1421 $(shell cat $(wordlist %(start)d,%(end)d,$(d_files)) >> $(depsdir)/all.deps)
1422 endif""" % { 'start': i, 'end': i + 999 })
1423
1424 # Add a check to make sure we tried to process all the .d files.
1425 all_deps += """
1426 ifneq ($(word %(last)d,$(d_files)),)
1427 $(error Found unprocessed dependency files (gyp didn't generate enough rules!))
1428 endif
1429 """ % { 'last': ((num_outputs / 1000) + 1) * 1000 + 1 }
1430
1431 root_makefile.write(SHARED_FOOTER % { 'generate_all_deps': all_deps })
12811432
12821433 root_makefile.close()
00 #!/usr/bin/python
11
2 # Copyright (c) 2009 Google Inc. All rights reserved.
2 # Copyright (c) 2011 The Chromium Authors. All rights reserved.
33 # Use of this source code is governed by a BSD-style license that can be
44 # found in the LICENSE file.
55
66 import ntpath
7 import os
78 import posixpath
8 import os
99 import re
1010 import subprocess
1111 import sys
1212
13 import gyp.common
14 import gyp.easy_xml as easy_xml
1315 import gyp.MSVSNew as MSVSNew
1416 import gyp.MSVSProject as MSVSProject
17 import gyp.MSVSSettings as MSVSSettings
1518 import gyp.MSVSToolFile as MSVSToolFile
1619 import gyp.MSVSUserFile as MSVSUserFile
1720 import gyp.MSVSVersion as MSVSVersion
18 import gyp.common
1921
2022
2123 # Regular expression for validating Visual Studio GUIDs. If the GUID
4042 'SHARED_INTERMEDIATE_DIR': '$(OutDir)/obj/global_intermediate',
4143 'OS': 'win',
4244 'PRODUCT_DIR': '$(OutDir)',
45
46 # TODO(jeanluc) The way we currently generate libraries makes Visual
47 # Studio 2010 unhappy. We get a lot of warnings like:
48 # warning MSB8012: TargetPath(...\Debug\gles2_c_lib.lib) does not match
49 # the Library's OutputFile property value (...\Debug\lib\gles2_c_lib.lib).
50 # This may cause your project to build incorrectly. To correct this,
51 # please make sure that $(OutDir), $(TargetName) and $(TargetExt) property
52 # values match the value specified in %(Lib.OutputFile).
53 # Despite the warnings, this compile correctly. It would be nice to get rid
54 # of the warnings.
55
56 # TODO(jeanluc) I had: 'LIB_DIR': '$(OutDir)lib',
4357 'LIB_DIR': '$(OutDir)/lib',
4458 'RULE_INPUT_ROOT': '$(InputName)',
4559 'RULE_INPUT_EXT': '$(InputExt)',
5569 'msvs_props',
5670 ]
5771
72
5873 generator_additional_non_configuration_keys = [
5974 'msvs_cygwin_dirs',
6075 'msvs_cygwin_shell',
6176 ]
6277
78
79 # List of precompiled header related keys.
80 precomp_keys = [
81 'msvs_precompiled_header',
82 'msvs_precompiled_source',
83 ]
84
85
6386 cached_username = None
87
88
6489 cached_domain = None
90
6591
6692 # TODO(gspencer): Switch the os.environ calls to be
6793 # win32api.GetDomainName() and win32api.GetUserName() once the
77103 username = os.environ.get('USERNAME')
78104 if not domain or not username:
79105 call = subprocess.Popen(['net', 'config', 'Workstation'],
80 stdout=subprocess.PIPE)
106 stdout=subprocess.PIPE)
81107 config = call.communicate()[0]
82108 username_re = re.compile('^User name\s+(\S+)', re.MULTILINE)
83109 username_match = username_re.search(config)
93119
94120 fixpath_prefix = None
95121
122
123 def _NormalizedSource(source):
124 """Normalize the path.
125
126 But not if that gets rid of a variable, as this may expand to something
127 larger than one directory.
128
129 Arguments:
130 source: The path to be normalize.d
131
132 Returns:
133 The normalized path.
134 """
135 normalized = os.path.normpath(source)
136 if source.count('$') == normalized.count('$'):
137 source = normalized
138 return source
139
140
96141 def _FixPath(path):
97142 """Convert paths to a form that will make sense in a vcproj file.
98143
104149 if fixpath_prefix and path and not os.path.isabs(path) and not path[0] == '$':
105150 path = os.path.join(fixpath_prefix, path)
106151 path = path.replace('/', '\\')
107 if len(path) > 0 and path[-1] == '\\':
152 path = _NormalizedSource(path)
153 if path and path[-1] == '\\':
108154 path = path[:-1]
109155 return path
110156
111157
112 def _SourceInFolders(sources, prefix=None, excluded=None):
158 def _FixPaths(paths):
159 """Fix each of the paths of the list."""
160 return [_FixPath(i) for i in paths]
161
162
163 def _ConvertSourcesToFilterHierarchy(sources, prefix=None, excluded=None):
113164 """Converts a list split source file paths into a vcproj folder hierarchy.
114165
115166 Arguments:
116167 sources: A list of source file paths split.
117168 prefix: A list of source file path layers meant to apply to each of sources.
169 excluded: A set of excluded files.
170
118171 Returns:
119172 A hierarchy of filenames and MSVSProject.Filter objects that matches the
120173 layout of the source tree.
121174 For example:
122 _SourceInFolders([['a', 'bob1.c'], ['b', 'bob2.c']], prefix=['joe'])
175 _ConvertSourcesToFilterHierarchy([['a', 'bob1.c'], ['b', 'bob2.c']],
176 prefix=['joe'])
123177 -->
124178 [MSVSProject.Filter('a', contents=['joe\\a\\bob1.c']),
125179 MSVSProject.Filter('b', contents=['joe\\b\\bob2.c'])]
131185 # Gather files into the final result, excluded, or folders.
132186 for s in sources:
133187 if len(s) == 1:
134 filename = '\\'.join(prefix + s)
188 filename = _NormalizedSource('\\'.join(prefix + s))
135189 if filename in excluded:
136190 excluded_result.append(filename)
137191 else:
147201 result.append(excluded_folder)
148202 # Populate all the folders.
149203 for f in folders:
150 contents = _SourceInFolders(folders[f], prefix=prefix + [f],
151 excluded=excluded)
204 contents = _ConvertSourcesToFilterHierarchy(folders[f], prefix=prefix + [f],
205 excluded=excluded)
152206 contents = MSVSProject.Filter(f, contents=contents)
153207 result.append(contents)
154208
195249 return '%s|%s' % (_ConfigBaseName(config_name, platform_name), platform_name)
196250
197251
198 def _PrepareActionRaw(spec, cmd, cygwin_shell, has_input_path, quote_cmd):
252 def _BuildCommandLineForRuleRaw(spec, cmd, cygwin_shell, has_input_path,
253 quote_cmd):
199254 if cygwin_shell:
200255 # Find path to cygwin.
201256 cygwin_dir = _FixPath(spec.get('msvs_cygwin_dirs', ['.'])[0])
215270 direct_cmd = ' '.join(direct_cmd)
216271 # TODO(quote): regularize quoting path names throughout the module
217272 cmd = (
218 '"$(ProjectDir)%(cygwin_dir)s\\setup_env.bat" && '
219 'set CYGWIN=nontsec&& ')
273 'call "$(ProjectDir)%(cygwin_dir)s\\setup_env.bat" && '
274 'set CYGWIN=nontsec&& ')
220275 if direct_cmd.find('NUMBER_OF_PROCESSORS') >= 0:
221276 cmd += 'set /a NUMBER_OF_PROCESSORS_PLUS_1=%%NUMBER_OF_PROCESSORS%%+1&& '
222277 if direct_cmd.find('INTDIR') >= 0:
225280 cmd += 'set OUTDIR=$(OutDir)&& '
226281 if has_input_path and direct_cmd.find('INPUTPATH') >= 0:
227282 cmd += 'set INPUTPATH=$(InputPath) && '
228 cmd += (
229 'bash -c "%(cmd)s"')
283 cmd += 'bash -c "%(cmd)s"'
230284 cmd = cmd % {'cygwin_dir': cygwin_dir,
231285 'cmd': direct_cmd}
232286 return cmd
233287 else:
234288 # Convert cat --> type to mimic unix.
235289 if cmd[0] == 'cat':
236 cmd = ['type'] + cmd[1:]
290 command = ['type']
291 else:
292 command = [cmd[0].replace('/', '\\')]
293 # Fix the paths
294 # If the argument starts with a slash, it's probably a command line switch
295 arguments = [i.startswith('/') and i or _FixPath(i) for i in cmd[1:]]
237296 if quote_cmd:
238297 # Support a mode for using cmd directly.
239298 # Convert any paths to native form (first element is used directly).
240299 # TODO(quote): regularize quoting path names throughout the module
241 direct_cmd = ([cmd[0].replace('/', '\\')] +
242 ['"%s"' % _FixPath(i) for i in cmd[1:]])
243 else:
244 direct_cmd = ([cmd[0].replace('/', '\\')] +
245 [_FixPath(i) for i in cmd[1:]])
300 arguments = ['"%s"' % i for i in arguments]
246301 # Collapse into a single command.
247 return ' '.join(direct_cmd)
248
249 def _PrepareAction(spec, rule, has_input_path):
302 return ' '.join(command + arguments)
303
304
305 def _BuildCommandLineForRule(spec, rule, has_input_path):
250306 # Find path to cygwin.
251307 cygwin_dir = _FixPath(spec.get('msvs_cygwin_dirs', ['.'])[0])
252308
260316 elif isinstance(mcs, str):
261317 mcs = int(mcs)
262318 quote_cmd = int(rule.get('msvs_quote_cmd', 1))
263 return _PrepareActionRaw(spec, rule['action'], mcs,
264 has_input_path, quote_cmd)
265
266
267 def _PickPrimaryInput(inputs):
268 # Pick second input as the primary one, unless there's only one.
269 # TODO(bradnelson): this is a bit of a hack,
270 # find something more general.
271 if len(inputs) > 1:
272 return inputs[1]
273 else:
274 return inputs[0]
275
276 def _SetRunAs(user_file, config_name, c_data, command,
277 environment={}, working_directory=""):
278 """Add a run_as rule to the user file.
279
280 Arguments:
281 user_file: The MSVSUserFile to add the command to.
282 config_name: The name of the configuration to add it to
283 c_data: The dict of the configuration to add it to
284 command: The path to the command to execute.
285 args: An array of arguments to the command. (optional)
286 working_directory: Directory to run the command in. (optional)
287 """
288 user_file.AddDebugSettings(_ConfigFullName(config_name, c_data),
289 command, environment, working_directory)
290
291 def _AddCustomBuildTool(p, spec, inputs, outputs, description, cmd):
319 return _BuildCommandLineForRuleRaw(spec, rule['action'], mcs, has_input_path,
320 quote_cmd)
321
322
323 def _AddActionStep(actions_dict, inputs, outputs, description, command):
324 """Merge action into an existing list of actions.
325
326 Care must be taken so that actions which have overlapping inputs either don't
327 get assigned to the same input, or get collapsed into one.
328
329 Arguments:
330 actions_dict: dictionary keyed on input name, which maps to a list of
331 dicts describing the actions attached to that input file.
332 inputs: list of inputs
333 outputs: list of outputs
334 description: description of the action
335 command: command line to execute
336 """
337 # Require there to be at least one input (call sites will ensure this).
338 assert inputs
339
340 action = {
341 'inputs': inputs,
342 'outputs': outputs,
343 'description': description,
344 'command': command,
345 }
346
347 # Pick where to stick this action.
348 # While less than optimal in terms of build time, attach them to the first
349 # input for now.
350 chosen_input = inputs[0]
351
352 # Add it there.
353 if chosen_input not in actions_dict:
354 actions_dict[chosen_input] = []
355 actions_dict[chosen_input].append(action)
356
357
358 def _AddCustomBuildToolForMSVS(p, spec, primary_input,
359 inputs, outputs, description, cmd):
292360 """Add a custom build tool to execute something.
293361
294362 Arguments:
295363 p: the target project
296364 spec: the target project dict
365 primary_input: input file to attach the build tool to
297366 inputs: list of inputs
298367 outputs: list of outputs
299368 description: description of the action
300369 cmd: command line to execute
301370 """
302 inputs = [_FixPath(i) for i in inputs]
303 outputs = [_FixPath(i) for i in outputs]
371 inputs = _FixPaths(inputs)
372 outputs = _FixPaths(outputs)
304373 tool = MSVSProject.Tool(
305 'VCCustomBuildTool', {
306 'Description': description,
307 'AdditionalDependencies': ';'.join(inputs),
308 'Outputs': ';'.join(outputs),
309 'CommandLine': cmd,
374 'VCCustomBuildTool',
375 {'Description': description,
376 'AdditionalDependencies': ';'.join(inputs),
377 'Outputs': ';'.join(outputs),
378 'CommandLine': cmd,
310379 })
311 primary_input = _PickPrimaryInput(inputs)
312380 # Add to the properties of primary input for each config.
313381 for config_name, c_data in spec['configurations'].iteritems():
314 p.AddFileConfig(primary_input,
382 p.AddFileConfig(_FixPath(primary_input),
315383 _ConfigFullName(config_name, c_data), tools=[tool])
384
385
386 def _AddAccumulatedActionsToMSVS(p, spec, actions_dict):
387 """Add actions accumulated into an actions_dict, merging as needed.
388
389 Arguments:
390 p: the target project
391 spec: the target project dict
392 actions_dict: dictionary keyed on input name, which maps to a list of
393 dicts describing the actions attached to that input file.
394 """
395 for primary_input in actions_dict:
396 inputs = set()
397 outputs = set()
398 descriptions = []
399 commands = []
400 for action in actions_dict[primary_input]:
401 inputs.update(set(action['inputs']))
402 outputs.update(set(action['outputs']))
403 descriptions.append(action['description'])
404 commands.append(action['command'])
405 # Add the custom build step for one input file.
406 description = ', and also '.join(descriptions)
407 command = '\r\n'.join(commands)
408 _AddCustomBuildToolForMSVS(p, spec,
409 primary_input=primary_input,
410 inputs=inputs,
411 outputs=outputs,
412 description=description,
413 cmd=command)
316414
317415
318416 def _RuleExpandPath(path, input_file):
350448 """Find the inputs and outputs generated by a rule.
351449
352450 Arguments:
353 rule: the rule in question
354 sources: the set of all known source files for this project
451 rule: the rule in question.
452 trigger_file: the main trigger for this rule.
355453 Returns:
356454 The pair of (inputs, outputs) involved in this rule.
357455 """
358 raw_inputs = rule.get('inputs', [])
359 raw_outputs = rule.get('outputs', [])
456 raw_inputs = _FixPaths(rule.get('inputs', []))
457 raw_outputs = _FixPaths(rule.get('outputs', []))
360458 inputs = set()
361459 outputs = set()
362460 inputs.add(trigger_file)
367465 return (inputs, outputs)
368466
369467
370 def _GenerateNativeRules(p, rules, output_dir, spec, options):
468 def _GenerateNativeRulesForMSVS(p, rules, output_dir, spec, options):
371469 """Generate a native rules file.
372470
373471 Arguments:
385483 for r in rules:
386484 rule_name = r['rule_name']
387485 rule_ext = r['extension']
388 inputs = [_FixPath(i) for i in r.get('inputs', [])]
389 outputs = [_FixPath(i) for i in r.get('outputs', [])]
390 cmd = _PrepareAction(spec, r, has_input_path=True)
486 inputs = _FixPaths(r.get('inputs', []))
487 outputs = _FixPaths(r.get('outputs', []))
488 cmd = _BuildCommandLineForRule(spec, r, has_input_path=True)
391489 rules_file.AddCustomBuildRule(name=rule_name,
392490 description=r.get('message', rule_name),
393491 extensions=[rule_ext],
407505 return path
408506
409507
410 def _GenerateExternalRules(p, rules, output_dir, spec,
508 def _GenerateExternalRules(rules, output_dir, spec,
411509 sources, options, actions_to_add):
412510 """Generate an external makefile to do a set of rules.
413511
414512 Arguments:
415 p: the target project
416513 rules: the list of rules to include
417514 output_dir: path containing project and gyp files
418515 spec: project specification data
419516 sources: set of sources known
420517 options: global generator options
518 actions_to_add: The list of actions we will add to.
421519 """
422520 filename = '%s_rules%s.mk' % (spec['target_name'], options.suffix)
423 file = gyp.common.WriteOnDiff(os.path.join(output_dir, filename))
521 mk_file = gyp.common.WriteOnDiff(os.path.join(output_dir, filename))
424522 # Find cygwin style versions of some paths.
425 file.write('OutDirCygwin:=$(shell cygpath -u "$(OutDir)")\n')
426 file.write('IntDirCygwin:=$(shell cygpath -u "$(IntDir)")\n')
523 mk_file.write('OutDirCygwin:=$(shell cygpath -u "$(OutDir)")\n')
524 mk_file.write('IntDirCygwin:=$(shell cygpath -u "$(IntDir)")\n')
427525 # Gather stuff needed to emit all: target.
428526 all_inputs = set()
429527 all_outputs = set()
444542 all_output_dirs.add(od)
445543 first_outputs_cyg = [_Cygwinify(i) for i in first_outputs]
446544 # Write out all: target, including mkdir for each output directory.
447 file.write('all: %s\n' % ' '.join(first_outputs_cyg))
545 mk_file.write('all: %s\n' % ' '.join(first_outputs_cyg))
448546 for od in all_output_dirs:
449 file.write('\tmkdir -p %s\n' % od)
450 file.write('\n')
547 mk_file.write('\tmkdir -p %s\n' % od)
548 mk_file.write('\n')
451549 # Define how each output is generated.
452550 for rule in rules:
453551 trigger_files = _FindRuleTriggerFiles(rule, sources)
461559 cmd = ['"%s"' % i for i in cmd]
462560 cmd = ' '.join(cmd)
463561 # Add it to the makefile.
464 file.write('%s: %s\n' % (' '.join(outputs), ' '.join(inputs)))
465 file.write('\t%s\n\n' % cmd)
562 mk_file.write('%s: %s\n' % (' '.join(outputs), ' '.join(inputs)))
563 mk_file.write('\t%s\n\n' % cmd)
466564 # Close up the file.
467 file.close()
565 mk_file.close()
468566
469567 # Add makefile to list of sources.
470568 sources.add(filename)
474572 'IntDir=$(IntDir)',
475573 '-j', '${NUMBER_OF_PROCESSORS_PLUS_1}',
476574 '-f', filename]
477 cmd = _PrepareActionRaw(spec, cmd, True, False, True)
478 # TODO(bradnelson): this won't be needed if we have a better way to pick
479 # the primary input.
575 cmd = _BuildCommandLineForRuleRaw(spec, cmd, True, False, True)
576 # Insert makefile as 0'th input, so it gets the action attached there,
577 # as this is easier to understand from in the IDE.
480578 all_inputs = list(all_inputs)
481 all_inputs.insert(1, filename)
482 actions_to_add.append({
483 'inputs': [_FixPath(i) for i in all_inputs],
484 'outputs': [_FixPath(i) for i in all_outputs],
485 'description': 'Running %s' % cmd,
486 'cmd': cmd,
487 })
579 all_inputs.insert(0, filename)
580 _AddActionStep(actions_to_add,
581 inputs=_FixPaths(all_inputs),
582 outputs=_FixPaths(all_outputs),
583 description='Running %s' % cmd,
584 command=cmd)
488585
489586
490587 def _EscapeEnvironmentVariableExpansion(s):
491 """Escapes any % characters so that Windows-style environment variable
492 expansions will leave them alone.
493 See http://connect.microsoft.com/VisualStudio/feedback/details/106127/cl-d-name-text-containing-percentage-characters-doesnt-compile
494 to understand why we have to do this."""
588 """Escapes % characters.
589
590 Escapes any % characters so that Windows-style environment variable
591 expansions will leave them alone.
592 See http://connect.microsoft.com/VisualStudio/feedback/details/106127/cl-d-name-text-containing-percentage-characters-doesnt-compile
593 to understand why we have to do this.
594
595 Args:
596 s: The string to be escaped.
597
598 Returns:
599 The escaped string.
600 """
495601 s = s.replace('%', '%%')
496602 return s
497603
498604
499605 quote_replacer_regex = re.compile(r'(\\*)"')
500 def _EscapeCommandLineArgument(s):
501 """Escapes a Windows command-line argument, so that the Win32
502 CommandLineToArgv function will turn the escaped result back into the
503 original string. See http://msdn.microsoft.com/en-us/library/17w5ykft.aspx
504 ("Parsing C++ Command-Line Arguments") to understand why we have to do
505 this."""
506 def replace(match):
606
607
608 def _EscapeCommandLineArgumentForMSVS(s):
609 """Escapes a Windows command-line argument.
610
611 So that the Win32 CommandLineToArgv function will turn the escaped result back
612 into the original string.
613 See http://msdn.microsoft.com/en-us/library/17w5ykft.aspx
614 ("Parsing C++ Command-Line Arguments") to understand why we have to do
615 this.
616
617 Args:
618 s: the string to be escaped.
619 Returns:
620 the escaped string.
621 """
622
623 def _Replace(match):
507624 # For a literal quote, CommandLineToArgv requires an odd number of
508625 # backslashes preceding it, and it produces half as many literal backslashes
509626 # (rounded down). So we need to produce 2n+1 backslashes.
510627 return 2 * match.group(1) + '\\"'
628
511629 # Escape all quotes so that they are interpreted literally.
512 s = quote_replacer_regex.sub(replace, s)
630 s = quote_replacer_regex.sub(_Replace, s)
513631 # Now add unescaped quotes so that any whitespace is interpreted literally.
514632 s = '"' + s + '"'
515633 return s
516634
517635
518636 delimiters_replacer_regex = re.compile(r'(\\*)([,;]+)')
637
638
519639 def _EscapeVCProjCommandLineArgListItem(s):
520 """The VCProj format stores string lists in a single string using commas and
521 semi-colons as separators, which must be quoted if they are to be
522 interpreted literally. However, command-line arguments may already have
523 quotes, and the VCProj parser is ignorant of the backslash escaping
524 convention used by CommandLineToArgv, so the command-line quotes and the
525 VCProj quotes may not be the same quotes. So to store a general
526 command-line argument in a VCProj list, we need to parse the existing
527 quoting according to VCProj's convention and quote any delimiters that are
528 not already quoted by that convention. The quotes that we add will also be
529 seen by CommandLineToArgv, so if backslashes precede them then we also have
530 to escape those backslashes according to the CommandLineToArgv
531 convention."""
532 def replace(match):
640 """Escapes command line arguments for MSVS.
641
642 The VCProj format stores string lists in a single string using commas and
643 semi-colons as separators, which must be quoted if they are to be
644 interpreted literally. However, command-line arguments may already have
645 quotes, and the VCProj parser is ignorant of the backslash escaping
646 convention used by CommandLineToArgv, so the command-line quotes and the
647 VCProj quotes may not be the same quotes. So to store a general
648 command-line argument in a VCProj list, we need to parse the existing
649 quoting according to VCProj's convention and quote any delimiters that are
650 not already quoted by that convention. The quotes that we add will also be
651 seen by CommandLineToArgv, so if backslashes precede them then we also have
652 to escape those backslashes according to the CommandLineToArgv
653 convention.
654
655 Args:
656 s: the string to be escaped.
657 Returns:
658 the escaped string.
659 """
660
661 def _Replace(match):
533662 # For a non-literal quote, CommandLineToArgv requires an even number of
534663 # backslashes preceding it, and it produces half as many literal
535664 # backslashes. So we need to produce 2n backslashes.
536665 return 2 * match.group(1) + '"' + match.group(2) + '"'
537 list = s.split('"')
666
667 segments = s.split('"')
538668 # The unquoted segments are at the even-numbered indices.
539 for i in range(0, len(list), 2):
540 list[i] = delimiters_replacer_regex.sub(replace, list[i])
669 for i in range(0, len(segments), 2):
670 segments[i] = delimiters_replacer_regex.sub(_Replace, segments[i])
541671 # Concatenate back into a single string
542 s = '"'.join(list)
543 if len(list) % 2 == 0:
672 s = '"'.join(segments)
673 if len(segments) % 2 == 0:
544674 # String ends while still quoted according to VCProj's convention. This
545675 # means the delimiter and the next list item that follow this one in the
546676 # .vcproj file will be misinterpreted as part of this item. There is nothing
549679 # the item to the end of the list does works, but that's only possible if
550680 # there's only one such item. Let's just warn the user.
551681 print >> sys.stderr, ('Warning: MSVS may misinterpret the odd number of ' +
552 'quotes in ' + s)
682 'quotes in ' + s)
553683 return s
554684
555685
556 def _EscapeCppDefine(s):
686 def _EscapeCppDefineForMSVS(s):
557687 """Escapes a CPP define so that it will reach the compiler unaltered."""
558688 s = _EscapeEnvironmentVariableExpansion(s)
559 s = _EscapeCommandLineArgument(s)
689 s = _EscapeCommandLineArgumentForMSVS(s)
560690 s = _EscapeVCProjCommandLineArgListItem(s)
561691 return s
562692
563693
564 def _GenerateRules(p, output_dir, options, spec,
565 sources, excluded_sources,
566 actions_to_add):
694 quote_replacer_regex2 = re.compile(r'(\\+)"')
695
696
697 def _EscapeCommandLineArgumentForMSBuild(s):
698 """Escapes a Windows command-line argument for use by MSBuild."""
699
700 def _Replace(match):
701 return (len(match.group(1))/2*4)*'\\' + '\\"'
702
703 # Escape all quotes so that they are interpreted literally.
704 s = quote_replacer_regex2.sub(_Replace, s)
705 return s
706
707
708 def _EscapeMSBuildSpecialCharacters(s):
709 escape_dictionary = {
710 '%': '%25',
711 '$': '%24',
712 '@': '%40',
713 "'": '%27',
714 ';': '%3B',
715 '?': '%3F',
716 '*': '%2A'
717 }
718 result = ''.join([escape_dictionary.get(c, c) for c in s])
719 return result
720
721
722 def _EscapeCppDefineForMSBuild(s):
723 """Escapes a CPP define so that it will reach the compiler unaltered."""
724 s = _EscapeEnvironmentVariableExpansion(s)
725 s = _EscapeCommandLineArgumentForMSBuild(s)
726 s = _EscapeMSBuildSpecialCharacters(s)
727 return s
728
729
730 def _GenerateRulesForMSVS(p, output_dir, options, spec,
731 sources, excluded_sources,
732 actions_to_add):
567733 """Generate all the rules for a particular project.
568734
569735 Arguments:
736 p: the project
570737 output_dir: directory to emit rules to
571738 options: global options passed to the generator
572739 spec: the specification for this project
580747
581748 # Handle rules that use a native rules file.
582749 if rules_native:
583 _GenerateNativeRules(p, rules_native, output_dir, spec, options)
750 _GenerateNativeRulesForMSVS(p, rules_native, output_dir, spec, options)
584751
585752 # Handle external rules (non-native rules).
586753 if rules_external:
587 _GenerateExternalRules(p, rules_external, output_dir, spec,
754 _GenerateExternalRules(rules_external, output_dir, spec,
588755 sources, options, actions_to_add)
589
756 _AdjustSourcesForRules(rules, sources, excluded_sources)
757
758
759 def _AdjustSourcesForRules(rules, sources, excluded_sources):
590760 # Add outputs generated by each rule (if applicable).
591761 for rule in rules:
592762 # Done if not processing outputs as sources.
593763 if int(rule.get('process_outputs_as_sources', False)):
594764 # Add in the outputs from this rule.
595765 trigger_files = _FindRuleTriggerFiles(rule, sources)
596 for tf in trigger_files:
597 inputs, outputs = _RuleInputsAndOutputs(rule, tf)
598 inputs.remove(tf)
766 for trigger_file in trigger_files:
767 inputs, outputs = _RuleInputsAndOutputs(rule, trigger_file)
768 inputs = set(_FixPaths(inputs))
769 outputs = set(_FixPaths(outputs))
770 inputs.remove(_FixPath(trigger_file))
599771 sources.update(inputs)
600772 excluded_sources.update(inputs)
601773 sources.update(outputs)
602774
603775
604 def _GenerateProject(vcproj_filename, build_file, spec, options, version):
605 """Generates a vcproj file.
606
607 Arguments:
608 vcproj_filename: Filename of the vcproj file to generate.
609 build_file: Filename of the .gyp file that the vcproj file comes from.
776 def _FilterActionsFromExcluded(excluded_sources, actions_to_add):
777 """Take inputs with actions attached out of the list of exclusions.
778
779 Arguments:
780 excluded_sources: list of source files not to be built.
781 actions_to_add: dict of actions keyed on source file they're attached to.
782 Returns:
783 excluded_sources with files that have actions attached removed.
784 """
785 must_keep = set(_FixPaths(actions_to_add.keys()))
786 return [s for s in excluded_sources if s not in must_keep]
787
788
789 def _GetDefaultConfiguration(spec):
790 return spec['configurations'][spec['default_configuration']]
791
792
793 def _GetGuidOfProject(proj_path, spec):
794 """Get the guid for the project.
795
796 Arguments:
797 proj_path: Path of the vcproj or vcxproj file to generate.
610798 spec: The target dictionary containing the properties of the target.
799 Returns:
800 the guid.
801 Raises:
802 ValueError: if the specified GUID is invalid.
611803 """
612804 # Pluck out the default configuration.
613 default_config = spec['configurations'][spec['default_configuration']]
805 default_config = _GetDefaultConfiguration(spec)
614806 # Decide the guid of the project.
615807 guid = default_config.get('msvs_guid')
616808 if guid:
617 if VALID_MSVS_GUID_CHARS.match(guid) == None:
809 if VALID_MSVS_GUID_CHARS.match(guid) is None:
618810 raise ValueError('Invalid MSVS guid: "%s". Must match regex: "%s".' %
619811 (guid, VALID_MSVS_GUID_CHARS.pattern))
620812 guid = '{%s}' % guid
813 guid = guid or MSVSNew.MakeGuid(proj_path)
814 return guid
815
816
817 def _GenerateProject(project, options, version):
818 """Generates a vcproj file.
819
820 Arguments:
821 project: the MSVSProject object.
822 options: global generator options.
823 version: the MSVSVersion object.
824 """
825 default_config = _GetDefaultConfiguration(project.spec)
621826
622827 # Skip emitting anything if told to with msvs_existing_vcproj option.
623828 if default_config.get('msvs_existing_vcproj'):
624 return guid
625
626 #print 'Generating %s' % vcproj_filename
627
628 vcproj_dir = os.path.dirname(vcproj_filename)
829 return
830
831 if version.UsesVcxproj():
832 _GenerateMSBuildProject(project, options, version)
833 else:
834 _GenerateMSVSProject(project, options, version)
835
836
837 def _GenerateMSVSProject(project, options, version):
838 """Generates a .vcproj file. It may create .rules and .user files too.
839
840 Arguments:
841 project: The project object we will generate the file for.
842 options: Global options passed to the generator.
843 version: The VisualStudioVersion object.
844 """
845 spec = project.spec
846 vcproj_dir = os.path.dirname(project.path)
629847 if vcproj_dir and not os.path.exists(vcproj_dir):
630848 os.makedirs(vcproj_dir)
631849
850 platforms = _GetUniquePlatforms(spec)
851 p = MSVSProject.Writer(project.path, version=version)
852 p.Create(spec['target_name'], guid=project.guid, platforms=platforms)
853
854 # Get directory project file is in.
855 gyp_dir = os.path.split(project.path)[0]
856 gyp_file = posixpath.split(project.build_file)[1]
857 gyp_path = _NormalizedSource(gyp_file)
858 relative_path_of_gyp_file = gyp.common.RelativePath(gyp_path, gyp_dir)
859
860 config_type = _GetMSVSConfigurationType(spec, project.build_file)
861 for config_name, config in spec['configurations'].iteritems():
862 _AddConfigurationToMSVSProject(p, spec, config_type, config_name, config)
863
864 # Prepare list of sources and excluded sources.
865 sources, excluded_sources = _PrepareListOfSources(spec,
866 relative_path_of_gyp_file)
867
868 # Add rules.
869 actions_to_add = {}
870 _GenerateRulesForMSVS(p, gyp_dir, options, spec,
871 sources, excluded_sources,
872 actions_to_add)
873 sources, excluded_sources, excluded_idl = (
874 _AdjustSourcesAndConvertToFilterHierarchy(
875 spec, options, gyp_dir, sources, excluded_sources))
876
877 # Add in files.
878 p.AddFiles(sources)
879
880 _AddToolFilesToMSVS(p, spec)
881 _HandlePreCompileHeaderStubs(p, spec)
882 _AddActions(actions_to_add, spec, relative_path_of_gyp_file)
883 _AddCopies(actions_to_add, spec)
884 _WriteMSVSUserFile(project.path, version, spec)
885
886 # NOTE: this stanza must appear after all actions have been decided.
887 # Don't excluded sources with actions attached, or they won't run.
888 excluded_sources = _FilterActionsFromExcluded(
889 excluded_sources, actions_to_add)
890 _ExcludeFilesFromBeingBuilt(p, spec, excluded_sources, excluded_idl)
891 _AddAccumulatedActionsToMSVS(p, spec, actions_to_add)
892
893 # Write it out.
894 p.Write()
895
896
897 def _GetUniquePlatforms(spec):
898 """Returns the list of unique platforms for this spec, e.g ['win32', ...].
899
900 Arguments:
901 spec: The target dictionary containing the properties of the target.
902 Returns:
903 The MSVSUserFile object created.
904 """
632905 # Gather list of unique platforms.
633906 platforms = set()
634907 for configuration in spec['configurations']:
635908 platforms.add(_ConfigPlatform(spec['configurations'][configuration]))
636909 platforms = list(platforms)
637
638 p = MSVSProject.Writer(vcproj_filename, version=version)
639 p.Create(spec['target_name'], guid=guid, platforms=platforms)
640
641 # Create the user file.
910 return platforms
911
912
913 def _CreateMSVSUserFile(proj_path, version, spec):
914 """Generates a .user file for the user running this Gyp program.
915
916 Arguments:
917 proj_path: The path of the project file being created. The .user file
918 shares the same path (with an appropriate suffix).
919 version: The VisualStudioVersion object.
920 spec: The target dictionary containing the properties of the target.
921 Returns:
922 The MSVSUserFile object created.
923 """
642924 (domain, username) = _GetDomainAndUserName()
643 vcuser_filename = '.'.join([vcproj_filename, domain, username, 'user'])
925 vcuser_filename = '.'.join([proj_path, domain, username, 'user'])
644926 user_file = MSVSUserFile.Writer(vcuser_filename, version=version)
645927 user_file.Create(spec['target_name'])
646
647 # Get directory project file is in.
648 gyp_dir = os.path.split(vcproj_filename)[0]
649
650 # Pick target configuration type.
928 return user_file
929
930
931 def _GetMSVSConfigurationType(spec, build_file):
932 """Returns the configuration type for this project.
933
934 It's a number defined by Microsoft. May raise an exception.
935
936 Args:
937 spec: The target dictionary containing the properties of the target.
938 build_file: The path of the gyp file.
939 Returns:
940 An integer, the configuration type.
941 """
651942 try:
652943 config_type = {
653944 'executable': '1', # .exe
657948 'none': '10', # Utility type
658949 'dummy_executable': '1', # .exe
659950 }[spec['type']]
660 except KeyError, e:
951 except KeyError:
661952 if spec.get('type'):
662953 raise Exception('Target type %s is not a valid target type for '
663954 'target %s in %s.' %
665956 else:
666957 raise Exception('Missing type field for target %s in %s.' %
667958 (spec['target_name'], build_file))
668
669 for config_name, c in spec['configurations'].iteritems():
670 # Process each configuration.
671 vsprops_dirs = c.get('msvs_props', [])
672 vsprops_dirs = [_FixPath(i) for i in vsprops_dirs]
673
674 # Prepare the list of tools as a dictionary.
675 tools = dict()
676
677 # Add in msvs_settings.
678 for tool in c.get('msvs_settings', {}):
679 settings = c['msvs_settings'][tool]
680 for setting in settings:
681 _ToolAppend(tools, tool, setting, settings[setting])
682
683 # Add in includes.
684 # TODO(bradnelson): include_dirs should really be flexible enough not to
685 # require this sort of thing.
686 include_dirs = (
687 c.get('include_dirs', []) +
688 c.get('msvs_system_include_dirs', []))
689 resource_include_dirs = c.get('resource_include_dirs', include_dirs)
690 include_dirs = [_FixPath(i) for i in include_dirs]
691 resource_include_dirs = [_FixPath(i) for i in resource_include_dirs]
959 return config_type
960
961
962 def _AddConfigurationToMSVSProject(p, spec, config_type, config_name, config):
963 """Adds a configuration to the MSVS project.
964
965 Many settings in a vcproj file are specific to a configuration. This
966 function the main part of the vcproj file that's configuration specific.
967
968 Arguments:
969 p: The target project being generated.
970 spec: The target dictionary containing the properties of the target.
971 config_type: The configuration type, a number as defined by Microsoft.
972 config_name: The name of the configuration.
973 config: The dictionnary that defines the special processing to be done
974 for this configuration.
975 """
976 # Get the information for this configuration
977 include_dirs, resource_include_dirs = _GetIncludeDirs(config)
978 libraries = _GetLibraries(spec)
979 out_file, vc_tool, _ = _GetOutputFilePathAndTool(spec)
980 defines = _GetDefines(config)
981 defines = [_EscapeCppDefineForMSVS(d) for d in defines]
982 disabled_warnings = _GetDisabledWarnings(config)
983 prebuild = config.get('msvs_prebuild')
984 postbuild = config.get('msvs_postbuild')
985 def_file = _GetModuleDefinition(spec)
986 precompiled_header = config.get('msvs_precompiled_header')
987
988 # Prepare the list of tools as a dictionary.
989 tools = dict()
990 # Add in user specified msvs_settings.
991 msvs_settings = config.get('msvs_settings', {})
992 MSVSSettings.ValidateMSVSSettings(msvs_settings)
993 for tool in msvs_settings:
994 settings = config['msvs_settings'][tool]
995 for setting in settings:
996 _ToolAppend(tools, tool, setting, settings[setting])
997 # Add the information to the appropriate tool
998 _ToolAppend(tools, 'VCCLCompilerTool',
999 'AdditionalIncludeDirectories', include_dirs)
1000 _ToolAppend(tools, 'VCResourceCompilerTool',
1001 'AdditionalIncludeDirectories', resource_include_dirs)
1002 # Add in libraries.
1003 _ToolAppend(tools, 'VCLinkerTool', 'AdditionalDependencies', libraries)
1004 if out_file:
1005 _ToolAppend(tools, vc_tool, 'OutputFile', out_file, only_if_unset=True)
1006 # Add defines.
1007 _ToolAppend(tools, 'VCCLCompilerTool', 'PreprocessorDefinitions', defines)
1008 _ToolAppend(tools, 'VCResourceCompilerTool', 'PreprocessorDefinitions',
1009 defines)
1010 # Change program database directory to prevent collisions.
1011 _ToolAppend(tools, 'VCCLCompilerTool', 'ProgramDataBaseFileName',
1012 '$(IntDir)\\$(ProjectName)\\vc80.pdb')
1013 # Add disabled warnings.
1014 _ToolAppend(tools, 'VCCLCompilerTool',
1015 'DisableSpecificWarnings', disabled_warnings)
1016 # Add Pre-build.
1017 _ToolAppend(tools, 'VCPreBuildEventTool', 'CommandLine', prebuild)
1018 # Add Post-build.
1019 _ToolAppend(tools, 'VCPostBuildEventTool', 'CommandLine', postbuild)
1020 # Turn on precompiled headers if appropriate.
1021 if precompiled_header:
1022 precompiled_header = os.path.split(precompiled_header)[1]
1023 _ToolAppend(tools, 'VCCLCompilerTool', 'UsePrecompiledHeader', '2')
6921024 _ToolAppend(tools, 'VCCLCompilerTool',
693 'AdditionalIncludeDirectories', include_dirs)
694 _ToolAppend(tools, 'VCResourceCompilerTool',
695 'AdditionalIncludeDirectories', resource_include_dirs)
696
697 # Add in libraries.
698 libraries = spec.get('libraries', [])
699 # Strip out -l, as it is not used on windows (but is needed so we can pass
700 # in libraries that are assumed to be in the default library path).
701 libraries = [re.sub('^(\-l)', '', lib) for lib in libraries]
702 # Add them.
703 _ToolAppend(tools, 'VCLinkerTool',
704 'AdditionalDependencies', libraries)
705
706 # Select a name for the output file.
707 output_file_map = {
708 'executable': ('VCLinkerTool', '$(OutDir)\\', '.exe'),
709 'shared_library': ('VCLinkerTool', '$(OutDir)\\', '.dll'),
710 'loadable_module': ('VCLinkerTool', '$(OutDir)\\', '.dll'),
711 'static_library': ('VCLibrarianTool', '$(OutDir)\\lib\\', '.lib'),
712 'dummy_executable': ('VCLinkerTool', '$(IntDir)\\', '.junk'),
713 }
714 output_file_props = output_file_map.get(spec['type'])
715 if output_file_props and int(spec.get('msvs_auto_output_file', 1)):
716 vc_tool, out_dir, suffix = output_file_props
717 out_dir = spec.get('product_dir', out_dir)
718 product_extension = spec.get('product_extension')
719 if product_extension:
720 suffix = '.' + product_extension
721 prefix = spec.get('product_prefix', '')
722 product_name = spec.get('product_name', '$(ProjectName)')
723 out_file = ntpath.join(out_dir, prefix + product_name + suffix)
724 _ToolAppend(tools, vc_tool, 'OutputFile', out_file,
725 only_if_unset=True)
726
727 # Add defines.
728 defines = []
729 for d in c.get('defines', []):
730 if type(d) == list:
731 fd = '='.join([str(dpart) for dpart in d])
1025 'PrecompiledHeaderThrough', precompiled_header)
1026 _ToolAppend(tools, 'VCCLCompilerTool',
1027 'ForcedIncludeFiles', precompiled_header)
1028 # Loadable modules don't generate import libraries;
1029 # tell dependent projects to not expect one.
1030 if spec['type'] == 'loadable_module':
1031 _ToolAppend(tools, 'VCLinkerTool', 'IgnoreImportLibrary', 'true')
1032 # Set the module definition file if any.
1033 if def_file:
1034 _ToolAppend(tools, 'VCLinkerTool', 'ModuleDefinitionFile', def_file)
1035
1036 _AddConfigurationToMSVS(p, spec, tools, config, config_type, config_name)
1037
1038
1039 def _GetIncludeDirs(config):
1040 """Returns the list of directories to be used for #include directives.
1041
1042 Arguments:
1043 config: The dictionnary that defines the special processing to be done
1044 for this configuration.
1045 Returns:
1046 The list of directory paths.
1047 """
1048 # TODO(bradnelson): include_dirs should really be flexible enough not to
1049 # require this sort of thing.
1050 include_dirs = (
1051 config.get('include_dirs', []) +
1052 config.get('msvs_system_include_dirs', []))
1053 resource_include_dirs = config.get('resource_include_dirs', include_dirs)
1054 include_dirs = _FixPaths(include_dirs)
1055 resource_include_dirs = _FixPaths(resource_include_dirs)
1056 return include_dirs, resource_include_dirs
1057
1058
1059 def _GetLibraries(spec):
1060 """Returns the list of libraries for this configuration.
1061
1062 Arguments:
1063 spec: The target dictionary containing the properties of the target.
1064 Returns:
1065 The list of directory paths.
1066 """
1067 libraries = spec.get('libraries', [])
1068 # Strip out -l, as it is not used on windows (but is needed so we can pass
1069 # in libraries that are assumed to be in the default library path).
1070 return [re.sub('^(\-l)', '', lib) for lib in libraries]
1071
1072
1073 def _GetOutputFilePathAndTool(spec):
1074 """Returns the path and tool to use for this target.
1075
1076 Figures out the path of the file this spec will create and the name of
1077 the VC tool that will create it.
1078
1079 Arguments:
1080 spec: The target dictionary containing the properties of the target.
1081 Returns:
1082 A triple of (file path, name of the vc tool, name of the msbuild tool)
1083 """
1084 # Select a name for the output file.
1085 out_file = ''
1086 vc_tool = ''
1087 msbuild_tool = ''
1088 output_file_map = {
1089 'executable': ('VCLinkerTool', 'Link', '$(OutDir)\\', '.exe'),
1090 'shared_library': ('VCLinkerTool', 'Link', '$(OutDir)\\', '.dll'),
1091 'loadable_module': ('VCLinkerTool', 'Link', '$(OutDir)\\', '.dll'),
1092 # TODO(jeanluc) If we want to avoid the MSB8012 warnings in
1093 # VisualStudio 2010, we will have to change the value of $(OutDir)
1094 # to contain the \lib suffix, rather than doing it as below.
1095 'static_library': ('VCLibrarianTool', 'Lib', '$(OutDir)\\lib\\', '.lib'),
1096 'dummy_executable': ('VCLinkerTool', 'Link', '$(IntDir)\\', '.junk'),
1097 }
1098 output_file_props = output_file_map.get(spec['type'])
1099 if output_file_props and int(spec.get('msvs_auto_output_file', 1)):
1100 vc_tool, msbuild_tool, out_dir, suffix = output_file_props
1101 out_dir = spec.get('product_dir', out_dir)
1102 product_extension = spec.get('product_extension')
1103 if product_extension:
1104 suffix = '.' + product_extension
1105 prefix = spec.get('product_prefix', '')
1106 product_name = spec.get('product_name', '$(ProjectName)')
1107 out_file = ntpath.join(out_dir, prefix + product_name + suffix)
1108 return out_file, vc_tool, msbuild_tool
1109
1110
1111 def _GetDefines(config):
1112 """Returns the list of preprocessor definitions for this configuation.
1113
1114 Arguments:
1115 config: The dictionnary that defines the special processing to be done
1116 for this configuration.
1117 Returns:
1118 The list of preprocessor definitions.
1119 """
1120 defines = []
1121 for d in config.get('defines', []):
1122 if type(d) == list:
1123 fd = '='.join([str(dpart) for dpart in d])
1124 else:
1125 fd = str(d)
1126 defines.append(fd)
1127 return defines
1128
1129
1130 def _GetDisabledWarnings(config):
1131 return [str(i) for i in config.get('msvs_disabled_warnings', [])]
1132
1133
1134 def _GetModuleDefinition(spec):
1135 def_file = ''
1136 if spec['type'] in ['shared_library', 'loadable_module']:
1137 def_files = [s for s in spec.get('sources', []) if s.endswith('.def')]
1138 if len(def_files) == 1:
1139 def_file = _FixPath(def_files[0])
1140 elif def_files:
1141 raise ValueError(
1142 'Multiple module definition files in one target, target %s lists '
1143 'multiple .def files: %s' % (
1144 spec['target_name'], ' '.join(def_files)))
1145 return def_file
1146
1147
1148 def _ConvertToolsToExpectedForm(tools):
1149 """Convert tools to a form expected by Visual Studio.
1150
1151 Arguments:
1152 tools: A dictionnary of settings; the tool name is the key.
1153 Returns:
1154 A list of Tool objects.
1155 """
1156 tool_list = []
1157 for tool, settings in tools.iteritems():
1158 # Collapse settings with lists.
1159 settings_fixed = {}
1160 for setting, value in settings.iteritems():
1161 if type(value) == list:
1162 if ((tool == 'VCLinkerTool' and
1163 setting == 'AdditionalDependencies') or
1164 setting == 'AdditionalOptions'):
1165 settings_fixed[setting] = ' '.join(value)
1166 else:
1167 settings_fixed[setting] = ';'.join(value)
7321168 else:
733 fd = str(d)
734 fd = _EscapeCppDefine(fd)
735 defines.append(fd)
736
737 _ToolAppend(tools, 'VCCLCompilerTool',
738 'PreprocessorDefinitions', defines)
739 _ToolAppend(tools, 'VCResourceCompilerTool',
740 'PreprocessorDefinitions', defines)
741
742 # Change program database directory to prevent collisions.
743 _ToolAppend(tools, 'VCCLCompilerTool', 'ProgramDataBaseFileName',
744 '$(IntDir)\\$(ProjectName)\\vc80.pdb')
745
746 # Add disabled warnings.
747 disabled_warnings = [str(i) for i in c.get('msvs_disabled_warnings', [])]
748 _ToolAppend(tools, 'VCCLCompilerTool',
749 'DisableSpecificWarnings', disabled_warnings)
750
751 # Add Pre-build.
752 prebuild = c.get('msvs_prebuild')
753 _ToolAppend(tools, 'VCPreBuildEventTool', 'CommandLine', prebuild)
754
755 # Add Post-build.
756 postbuild = c.get('msvs_postbuild')
757 _ToolAppend(tools, 'VCPostBuildEventTool', 'CommandLine', postbuild)
758
759 # Turn on precompiled headers if appropriate.
760 header = c.get('msvs_precompiled_header')
761 if header:
762 header = os.path.split(header)[1]
763 _ToolAppend(tools, 'VCCLCompilerTool', 'UsePrecompiledHeader', '2')
764 _ToolAppend(tools, 'VCCLCompilerTool',
765 'PrecompiledHeaderThrough', header)
766 _ToolAppend(tools, 'VCCLCompilerTool',
767 'ForcedIncludeFiles', header)
768
769 # Loadable modules don't generate import libraries;
770 # tell dependent projects to not expect one.
771 if spec['type'] == 'loadable_module':
772 _ToolAppend(tools, 'VCLinkerTool', 'IgnoreImportLibrary', 'true')
773
774 # Set the module definition file if any.
775 if spec['type'] in ['shared_library', 'loadable_module']:
776 def_files = [s for s in spec.get('sources', []) if s.endswith('.def')]
777 if len(def_files) == 1:
778 _ToolAppend(tools, 'VCLinkerTool', 'ModuleDefinitionFile',
779 _FixPath(def_files[0]))
780 elif def_files:
781 raise ValueError('Multiple module definition files in one target, '
782 'target %s lists multiple .def files: %s' % (
783 spec['target_name'], ' '.join(def_files)))
784
785 # Convert tools to expected form.
786 tool_list = []
787 for tool, settings in tools.iteritems():
788 # Collapse settings with lists.
789 settings_fixed = {}
790 for setting, value in settings.iteritems():
791 if type(value) == list:
792 if ((tool == 'VCLinkerTool' and
793 setting == 'AdditionalDependencies') or
794 setting == 'AdditionalOptions'):
795 settings_fixed[setting] = ' '.join(value)
796 else:
797 settings_fixed[setting] = ';'.join(value)
798 else:
799 settings_fixed[setting] = value
800 # Add in this tool.
801 tool_list.append(MSVSProject.Tool(tool, settings_fixed))
802
803 # Prepare configuration attributes.
804 prepared_attrs = {}
805 source_attrs = c.get('msvs_configuration_attributes', {})
806 for a in source_attrs:
807 prepared_attrs[a] = source_attrs[a]
808 # Add props files.
809 if vsprops_dirs:
810 prepared_attrs['InheritedPropertySheets'] = ';'.join(vsprops_dirs)
811 # Set configuration type.
812 prepared_attrs['ConfigurationType'] = config_type
813 if not prepared_attrs.has_key('OutputDirectory'):
814 prepared_attrs['OutputDirectory'] = '$(SolutionDir)$(ConfigurationName)'
815 if not prepared_attrs.has_key('IntermediateDirectory'):
816 intermediate = '$(ConfigurationName)\\obj\\$(ProjectName)'
817 prepared_attrs['IntermediateDirectory'] = intermediate
818
819 # Add in this configuration.
820 p.AddConfig(_ConfigFullName(config_name, c),
821 attrs=prepared_attrs, tools=tool_list)
822
823 # Prepare list of sources and excluded sources.
824 sources = set(spec.get('sources', []))
1169 settings_fixed[setting] = value
1170 # Add in this tool.
1171 tool_list.append(MSVSProject.Tool(tool, settings_fixed))
1172 return tool_list
1173
1174
1175 def _AddConfigurationToMSVS(p, spec, tools, config, config_type, config_name):
1176 """Add to the project file the configuration specified by config.
1177
1178 Arguments:
1179 p: The target project being generated.
1180 spec: the target project dict.
1181 tools: A dictionnary of settings; the tool name is the key.
1182 config: The dictionnary that defines the special processing to be done
1183 for this configuration.
1184 config_type: The configuration type, a number as defined by Microsoft.
1185 config_name: The name of the configuration.
1186 """
1187 attributes = _GetMSVSAttributes(spec, config, config_type)
1188 # Add in this configuration.
1189 tool_list = _ConvertToolsToExpectedForm(tools)
1190 p.AddConfig(_ConfigFullName(config_name, config),
1191 attrs=attributes, tools=tool_list)
1192
1193
1194 def _GetMSVSAttributes(spec, config, config_type):
1195 # Prepare configuration attributes.
1196 prepared_attrs = {}
1197 source_attrs = config.get('msvs_configuration_attributes', {})
1198 for a in source_attrs:
1199 prepared_attrs[a] = source_attrs[a]
1200 # Add props files.
1201 vsprops_dirs = config.get('msvs_props', [])
1202 vsprops_dirs = _FixPaths(vsprops_dirs)
1203 if vsprops_dirs:
1204 prepared_attrs['InheritedPropertySheets'] = ';'.join(vsprops_dirs)
1205 # Set configuration type.
1206 prepared_attrs['ConfigurationType'] = config_type
1207 output_dir = prepared_attrs.get('OutputDirectory',
1208 '$(SolutionDir)$(ConfigurationName)')
1209 # TODO(jeanluc) If we want to avoid the MSB8012 warning, we should
1210 # add code like the following to place libraries in their own directory.
1211 # if config_type == '4':
1212 # output_dir = spec.get('product_dir', output_dir + '\\lib')
1213 prepared_attrs['OutputDirectory'] = output_dir
1214 if 'IntermediateDirectory' not in prepared_attrs:
1215 intermediate = '$(ConfigurationName)\\obj\\$(ProjectName)'
1216 prepared_attrs['IntermediateDirectory'] = intermediate
1217 return prepared_attrs
1218
1219
1220 def _AddNormalizedSources(sources_set, sources_array):
1221 sources = [_NormalizedSource(s) for s in sources_array]
1222 sources_set.update(set(sources))
1223
1224
1225 def _PrepareListOfSources(spec, relative_path_of_gyp_file):
1226 """Prepare list of sources and excluded sources.
1227
1228 Besides the sources specified directly in the spec, adds the gyp file so
1229 that a change to it will cause a re-compile. Also adds appropriate sources
1230 for actions and copies. Assumes later stage will un-exclude files which
1231 have custom build steps attached.
1232
1233 Arguments:
1234 spec: The target dictionary containing the properties of the target.
1235 relative_path_of_gyp_file: The relative path of the gyp file.
1236 Returns:
1237 A pair of (list of sources, list of excluded sources)
1238 """
1239 sources = set()
1240 _AddNormalizedSources(sources, spec.get('sources', []))
8251241 excluded_sources = set()
8261242 # Add in the gyp file.
827 gyp_file = os.path.split(build_file)[1]
828 sources.add(gyp_file)
1243 sources.add(relative_path_of_gyp_file)
1244
8291245 # Add in 'action' inputs and outputs.
8301246 for a in spec.get('actions', []):
831 inputs = a.get('inputs')
832 if not inputs:
833 # This is an action with no inputs. Make the primary input
834 # by the .gyp file itself so Visual Studio has a place to
835 # hang the custom build rule.
836 inputs = [gyp_file]
837 a['inputs'] = inputs
838 primary_input = _PickPrimaryInput(inputs)
1247 inputs = a.get('inputs', [])
1248 inputs = [_NormalizedSource(i) for i in inputs]
1249 # Add all inputs to sources and excluded sources.
8391250 inputs = set(inputs)
8401251 sources.update(inputs)
841 inputs.remove(primary_input)
8421252 excluded_sources.update(inputs)
8431253 if int(a.get('process_outputs_as_sources', False)):
844 outputs = set(a.get('outputs', []))
845 sources.update(outputs)
1254 _AddNormalizedSources(sources, a.get('outputs', []))
8461255 # Add in 'copies' inputs and outputs.
8471256 for cpy in spec.get('copies', []):
848 files = set(cpy.get('files', []))
849 sources.update(files)
850
851 # Add rules.
852 actions_to_add = []
853 _GenerateRules(p, gyp_dir, options, spec,
854 sources, excluded_sources,
855 actions_to_add)
856
1257 _AddNormalizedSources(sources, cpy.get('files', []))
1258 return (sources, excluded_sources)
1259
1260
1261 def _AdjustSourcesAndConvertToFilterHierarchy(
1262 spec, options, gyp_dir, sources, excluded_sources):
1263 """Adjusts the list of sources and excluded sources.
1264
1265 Also converts the sets to lists.
1266
1267 Arguments:
1268 spec: The target dictionary containing the properties of the target.
1269 options: Global generator options.
1270 gyp_dir: The path to the gyp file being processed.
1271 sources: A set of sources to be included for this project.
1272 excluded_sources: A set of sources to be excluded for this project.
1273 Returns:
1274 A trio of (list of sources, list of excluded sources,
1275 path of excluded IDL file)
1276 """
8571277 # Exclude excluded sources coming into the generator.
8581278 excluded_sources.update(set(spec.get('sources_excluded', [])))
8591279 # Add excluded sources into sources for good measure.
8611281 # Convert to proper windows form.
8621282 # NOTE: sources goes from being a set to a list here.
8631283 # NOTE: excluded_sources goes from being a set to a list here.
864 sources = [_FixPath(i) for i in sources]
1284 sources = _FixPaths(sources)
8651285 # Convert to proper windows form.
866 excluded_sources = [_FixPath(i) for i in excluded_sources]
867
1286 excluded_sources = _FixPaths(excluded_sources)
1287
1288 excluded_idl = _IdlFilesHandledNonNatively(spec, sources)
1289
1290 precompiled_related = _GetPrecompileRelatedFiles(spec)
1291 # Find the excluded ones, minus the precompiled header related ones.
1292 fully_excluded = [i for i in excluded_sources if i not in precompiled_related]
1293
1294 # Convert to folders and the right slashes.
1295 sources = [i.split('\\') for i in sources]
1296 sources = _ConvertSourcesToFilterHierarchy(sources, excluded=fully_excluded)
1297 # Add in dummy file for type none.
1298 if spec['type'] == 'dummy_executable':
1299 # Pull in a dummy main so it can link successfully.
1300 dummy_relpath = gyp.common.RelativePath(
1301 options.depth + '\\tools\\gyp\\gyp_dummy.c', gyp_dir)
1302 sources.append(dummy_relpath)
1303
1304 return sources, excluded_sources, excluded_idl
1305
1306
1307 def _IdlFilesHandledNonNatively(spec, sources):
8681308 # If any non-native rules use 'idl' as an extension exclude idl files.
8691309 # Gather a list here to use later.
8701310 using_idl = False
8761316 excluded_idl = [i for i in sources if i.endswith('.idl')]
8771317 else:
8781318 excluded_idl = []
879
880 # List of precompiled header related keys.
881 precomp_keys = [
882 'msvs_precompiled_header',
883 'msvs_precompiled_source',
884 ]
885
1319 return excluded_idl
1320
1321
1322 def _GetPrecompileRelatedFiles(spec):
8861323 # Gather a list of precompiled header related sources.
8871324 precompiled_related = []
888 for config_name, c in spec['configurations'].iteritems():
1325 for _, config in spec['configurations'].iteritems():
8891326 for k in precomp_keys:
890 f = c.get(k)
1327 f = config.get(k)
8911328 if f:
8921329 precompiled_related.append(_FixPath(f))
893
894 # Find the excluded ones, minus the precompiled header related ones.
895 fully_excluded = [i for i in excluded_sources if i not in precompiled_related]
896
897 # Convert to folders and the right slashes.
898 sources = [i.split('\\') for i in sources]
899 sources = _SourceInFolders(sources, excluded=fully_excluded)
900 # Add in dummy file for type none.
901 if spec['type'] == 'dummy_executable':
902 # Pull in a dummy main so it can link successfully.
903 dummy_relpath = gyp.common.RelativePath(
904 options.depth + '\\tools\\gyp\\gyp_dummy.c', gyp_dir)
905 sources.append(dummy_relpath)
906 # Add in files.
907 p.AddFiles(sources)
908
909 # Add deferred actions to add.
910 for a in actions_to_add:
911 _AddCustomBuildTool(p, spec,
912 inputs=a['inputs'],
913 outputs=a['outputs'],
914 description=a['description'],
915 cmd=a['cmd'])
916
1330 return precompiled_related
1331
1332
1333 def _ExcludeFilesFromBeingBuilt(p, spec, excluded_sources, excluded_idl):
1334 exclusions = _GetExcludedFilesFromBuild(spec, excluded_sources, excluded_idl)
1335 for file_name, excluded_configs in exclusions.iteritems():
1336 for config_name, config in excluded_configs:
1337 p.AddFileConfig(file_name, _ConfigFullName(config_name, config),
1338 {'ExcludedFromBuild': 'true'})
1339
1340
1341 def _GetExcludedFilesFromBuild(spec, excluded_sources, excluded_idl):
1342 exclusions = {}
9171343 # Exclude excluded sources from being built.
9181344 for f in excluded_sources:
919 for config_name, c in spec['configurations'].iteritems():
920 precomped = [_FixPath(c.get(i, '')) for i in precomp_keys]
1345 excluded_configs = []
1346 for config_name, config in spec['configurations'].iteritems():
1347 precomped = [_FixPath(config.get(i, '')) for i in precomp_keys]
9211348 # Don't do this for ones that are precompiled header related.
9221349 if f not in precomped:
923 p.AddFileConfig(f, _ConfigFullName(config_name, c),
924 {'ExcludedFromBuild': 'true'})
925
1350 excluded_configs.append((config_name, config))
1351 exclusions[f] = excluded_configs
9261352 # If any non-native rules use 'idl' as an extension exclude idl files.
9271353 # Exclude them now.
928 for config_name, c in spec['configurations'].iteritems():
929 for f in excluded_idl:
930 p.AddFileConfig(f, _ConfigFullName(config_name, c),
931 {'ExcludedFromBuild': 'true'})
932
1354 for f in excluded_idl:
1355 excluded_configs = []
1356 for config_name, config in spec['configurations'].iteritems():
1357 excluded_configs.append((config_name, config))
1358 exclusions[f] = excluded_configs
1359 return exclusions
1360
1361
1362 def _AddToolFilesToMSVS(p, spec):
9331363 # Add in tool files (rules).
9341364 tool_files = set()
935 for config_name, c in spec['configurations'].iteritems():
936 for f in c.get('msvs_tool_files', []):
1365 for _, config in spec['configurations'].iteritems():
1366 for f in config.get('msvs_tool_files', []):
9371367 tool_files.add(f)
9381368 for f in tool_files:
9391369 p.AddToolFile(f)
9401370
1371
1372 def _HandlePreCompileHeaderStubs(p, spec):
9411373 # Handle pre-compiled headers source stubs specially.
942 for config_name, c in spec['configurations'].iteritems():
943 source = c.get('msvs_precompiled_source')
1374 for config_name, config in spec['configurations'].iteritems():
1375 source = config.get('msvs_precompiled_source')
9441376 if source:
9451377 source = _FixPath(source)
9461378 # UsePrecompiledHeader=1 for if using precompiled headers.
9471379 tool = MSVSProject.Tool('VCCLCompilerTool',
9481380 {'UsePrecompiledHeader': '1'})
949 p.AddFileConfig(source, _ConfigFullName(config_name, c),
1381 p.AddFileConfig(source, _ConfigFullName(config_name, config),
9501382 {}, tools=[tool])
9511383
1384
1385 def _AddActions(actions_to_add, spec, relative_path_of_gyp_file):
9521386 # Add actions.
9531387 actions = spec.get('actions', [])
9541388 for a in actions:
955 cmd = _PrepareAction(spec, a, has_input_path=False)
956 _AddCustomBuildTool(p, spec,
957 inputs=a.get('inputs', []),
958 outputs=a.get('outputs', []),
959 description=a.get('message', a['action_name']),
960 cmd=cmd)
961
1389 cmd = _BuildCommandLineForRule(spec, a, has_input_path=False)
1390 # Attach actions to the gyp file if nothing else is there.
1391 inputs = a.get('inputs') or [relative_path_of_gyp_file]
1392 # Add the action.
1393 _AddActionStep(actions_to_add,
1394 inputs=inputs,
1395 outputs=a.get('outputs', []),
1396 description=a.get('message', a['action_name']),
1397 command=cmd)
1398
1399
1400 def _WriteMSVSUserFile(project_path, version, spec):
9621401 # Add run_as and test targets.
963 has_run_as = False
964 if spec.get('run_as') or int(spec.get('test', 0)):
965 has_run_as = True
966 run_as = spec.get('run_as', {
967 'action' : ['$(TargetPath)', '--gtest_print_time'],
968 })
969 working_directory = run_as.get('working_directory', '.')
1402 if 'run_as' in spec:
1403 run_as = spec['run_as']
9701404 action = run_as.get('action', [])
9711405 environment = run_as.get('environment', [])
972 for config_name, c_data in spec['configurations'].iteritems():
973 _SetRunAs(user_file, config_name, c_data,
974 action, environment, working_directory)
975
1406 working_directory = run_as.get('working_directory', '.')
1407 elif int(spec.get('test', 0)):
1408 action = ['$(TargetPath)', '--gtest_print_time']
1409 environment = []
1410 working_directory = '.'
1411 else:
1412 return # Nothing to add
1413 # Write out the user file.
1414 user_file = _CreateMSVSUserFile(project_path, version, spec)
1415 for config_name, c_data in spec['configurations'].iteritems():
1416 user_file.AddDebugSettings(_ConfigFullName(config_name, c_data),
1417 action, environment, working_directory)
1418 user_file.Write()
1419
1420
1421 def _AddCopies(actions_to_add, spec):
1422 copies = _GetCopies(spec)
1423 for inputs, outputs, cmd, description in copies:
1424 _AddActionStep(actions_to_add, inputs=inputs, outputs=outputs,
1425 description=description, command=cmd)
1426
1427
1428 def _GetCopies(spec):
1429 copies = []
9761430 # Add copies.
9771431 for cpy in spec.get('copies', []):
9781432 for src in cpy.get('files', []):
9791433 dst = os.path.join(cpy['destination'], os.path.basename(src))
980 # _AddCustomBuildTool() will call _FixPath() on the inputs and
1434 # _AddCustomBuildToolForMSVS() will call _FixPath() on the inputs and
9811435 # outputs, so do the same for our generated command line.
9821436 if src.endswith('/'):
9831437 src_bare = src[:-1]
9851439 outer_dir = posixpath.split(src_bare)[1]
9861440 cmd = 'cd "%s" && xcopy /e /f /y "%s" "%s\\%s\\"' % (
9871441 _FixPath(base_dir), outer_dir, _FixPath(dst), outer_dir)
988 _AddCustomBuildTool(p, spec,
989 inputs=[src],
990 outputs=['dummy_copies', dst],
991 description='Copying %s to %s' % (src, dst),
992 cmd=cmd)
1442 copies.append(([src], ['dummy_copies', dst], cmd,
1443 'Copying %s to %s' % (src, dst)))
9931444 else:
9941445 cmd = 'mkdir "%s" 2>nul & set ERRORLEVEL=0 & copy /Y "%s" "%s"' % (
9951446 _FixPath(cpy['destination']), _FixPath(src), _FixPath(dst))
996 _AddCustomBuildTool(p, spec,
997 inputs=[src], outputs=[dst],
998 description='Copying %s to %s' % (src, dst),
999 cmd=cmd)
1000
1001 # Write it out.
1002 p.Write()
1003
1004 # Write out the user file, but only if we need to.
1005 if has_run_as:
1006 user_file.Write()
1007
1008 # Return the guid so we can refer to it elsewhere.
1009 return p.guid
1447 copies.append(([src], [dst], cmd, 'Copying %s to %s' % (src, dst)))
1448 return copies
10101449
10111450
10121451 def _GetPathDict(root, path):
1013 if path == '':
1452 if not path:
10141453 return root
10151454 parent, folder = os.path.split(path)
10161455 parent_dict = _GetPathDict(root, parent)
10481487 return node[node.keys()[0]]
10491488 if type(node) != dict:
10501489 return node
1051 for child in node.keys():
1490 for child in node:
10521491 node[child] = _CollapseSingles(child, node[child])
10531492 return node
10541493
10551494
1056 def _GatherSolutionFolders(project_objs, flat):
1495 def _GatherSolutionFolders(sln_projects, project_objects, flat):
10571496 root = {}
10581497 # Convert into a tree of dicts on path.
1059 for p in project_objs.keys():
1498 for p in sln_projects:
10601499 gyp_file, target = gyp.common.ParseQualifiedTarget(p)[0:2]
10611500 gyp_dir = os.path.dirname(gyp_file)
10621501 path_dict = _GetPathDict(root, gyp_dir)
1063 path_dict[target + '.vcproj'] = project_objs[p]
1502 path_dict[target + '.vcproj'] = project_objects[p]
10641503 # Walk down from the top until we hit a folder that has more than one entry.
10651504 # In practice, this strips the top-level "src/" dir from the hierarchy in
10661505 # the solution.
10721511 return _DictsToFolders('', root, flat)
10731512
10741513
1075 def _ProjectObject(sln, qualified_target, project_objs, projects):
1076 # Done if this project has an object.
1077 if project_objs.get(qualified_target):
1078 return project_objs[qualified_target]
1079 # Get dependencies for this project.
1080 spec = projects[qualified_target]['spec']
1081 deps = spec.get('dependencies', [])
1082 # Get objects for each dependency.
1083 deps = [_ProjectObject(sln, d, project_objs, projects) for d in deps]
1084 # Find relative path to vcproj from sln.
1085 vcproj_rel_path = gyp.common.RelativePath(
1086 projects[qualified_target]['vcproj_path'], os.path.split(sln)[0])
1087 vcproj_rel_path = _FixPath(vcproj_rel_path)
1514 def _GetPathOfProject(qualified_target, spec, options, msvs_version):
1515 default_config = _GetDefaultConfiguration(spec)
1516 proj_filename = default_config.get('msvs_existing_vcproj')
1517 if not proj_filename:
1518 proj_filename = (spec['target_name'] + options.suffix +
1519 msvs_version.ProjectExtension())
1520
1521 build_file = gyp.common.BuildFile(qualified_target)
1522 proj_path = os.path.join(os.path.split(build_file)[0], proj_filename)
1523 fix_prefix = None
1524 if options.generator_output:
1525 project_dir_path = os.path.dirname(os.path.abspath(proj_path))
1526 proj_path = os.path.join(options.generator_output, proj_path)
1527 fix_prefix = gyp.common.RelativePath(project_dir_path,
1528 os.path.dirname(proj_path))
1529 return proj_path, fix_prefix
1530
1531
1532 def _GetPlatformOverridesOfProject(spec):
10881533 # Prepare a dict indicating which project configurations are used for which
10891534 # solution configurations for this target.
10901535 config_platform_overrides = {}
10941539 fixed_config_fullname = '%s|%s' % (
10951540 _ConfigBaseName(config_name, _ConfigPlatform(c)), platform)
10961541 config_platform_overrides[config_fullname] = fixed_config_fullname
1097 # Create object for this project.
1098 obj = MSVSNew.MSVSProject(
1099 vcproj_rel_path,
1100 name=spec['target_name'],
1101 guid=projects[qualified_target]['guid'],
1102 dependencies=deps,
1103 config_platform_overrides=config_platform_overrides)
1104 # Store it to the list of objects.
1105 project_objs[qualified_target] = obj
1106 # Return project object.
1107 return obj
1542 return config_platform_overrides
1543
1544
1545 def _CreateProjectObjects(target_list, target_dicts, options, msvs_version):
1546 """Create a MSVSProject object for the targets found in target list.
1547
1548 Arguments:
1549 target_list: the list of targets to generate project objects for.
1550 target_dicts: the dictionary of specifications.
1551 options: global generator options.
1552 msvs_version: the MSVSVersion object.
1553 Returns:
1554 A set of created projects, keyed by target.
1555 """
1556 global fixpath_prefix
1557 # Generate each project.
1558 projects = {}
1559 for qualified_target in target_list:
1560 spec = target_dicts[qualified_target]
1561 if spec['toolset'] != 'target':
1562 raise Exception(
1563 'Multiple toolsets not supported in msvs build (target %s)' %
1564 qualified_target)
1565 proj_path, fixpath_prefix = _GetPathOfProject(qualified_target, spec,
1566 options, msvs_version)
1567 guid = _GetGuidOfProject(proj_path, spec)
1568 overrides = _GetPlatformOverridesOfProject(spec)
1569 build_file = gyp.common.BuildFile(qualified_target)
1570 # Create object for this project.
1571 obj = MSVSNew.MSVSProject(
1572 _FixPath(proj_path),
1573 name=spec['target_name'],
1574 guid=guid,
1575 spec=spec,
1576 build_file=build_file,
1577 config_platform_overrides=overrides,
1578 fixpath_prefix=fixpath_prefix)
1579 projects[qualified_target] = obj
1580 # Set all the dependencies
1581 for project in projects.values():
1582 deps = project.spec.get('dependencies', [])
1583 deps = [projects[d] for d in deps]
1584 project.set_dependencies(deps)
1585 return projects
11081586
11091587
11101588 def CalculateVariables(default_variables, params):
11131591 generator_flags = params.get('generator_flags', {})
11141592
11151593 # Select project file format version (if unset, default to auto detecting).
1116 msvs_version = \
1117 MSVSVersion.SelectVisualStudioVersion(generator_flags.get('msvs_version',
1118 'auto'))
1594 msvs_version = MSVSVersion.SelectVisualStudioVersion(
1595 generator_flags.get('msvs_version', 'auto'))
11191596 # Stash msvs_version for later (so we don't have to probe the system twice).
11201597 params['msvs_version'] = msvs_version
11211598
11451622 global fixpath_prefix
11461623
11471624 options = params['options']
1148 generator_flags = params.get('generator_flags', {})
11491625
11501626 # Get the project file format version back out of where we stashed it in
11511627 # GeneratorCalculatedVariables.
11541630 # Prepare the set of configurations.
11551631 configs = set()
11561632 for qualified_target in target_list:
1157 build_file = gyp.common.BuildFile(qualified_target)
11581633 spec = target_dicts[qualified_target]
1159 for config_name, c in spec['configurations'].iteritems():
1160 configs.add(_ConfigFullName(config_name, c))
1634 for config_name, config in spec['configurations'].iteritems():
1635 configs.add(_ConfigFullName(config_name, config))
11611636 configs = list(configs)
11621637
1638 # Figure out all the projects that will be generated and their guids
1639 project_objects = _CreateProjectObjects(target_list, target_dicts, options,
1640 msvs_version)
1641
11631642 # Generate each project.
1164 projects = {}
1165 for qualified_target in target_list:
1166 build_file = gyp.common.BuildFile(qualified_target)
1167 spec = target_dicts[qualified_target]
1168 if spec['toolset'] != 'target':
1169 raise Exception(
1170 'Multiple toolsets not supported in msvs build (target %s)' %
1171 qualified_target)
1172 default_config = spec['configurations'][spec['default_configuration']]
1173 vcproj_filename = default_config.get('msvs_existing_vcproj')
1174 if not vcproj_filename:
1175 vcproj_filename = spec['target_name'] + options.suffix + '.vcproj'
1176 vcproj_path = os.path.join(os.path.split(build_file)[0], vcproj_filename)
1177 if options.generator_output:
1178 projectDirPath = os.path.dirname(os.path.abspath(vcproj_path))
1179 vcproj_path = os.path.join(options.generator_output, vcproj_path)
1180 fixpath_prefix = gyp.common.RelativePath(projectDirPath,
1181 os.path.dirname(vcproj_path))
1182 projects[qualified_target] = {
1183 'vcproj_path': vcproj_path,
1184 'guid': _GenerateProject(vcproj_path, build_file,
1185 spec, options, version=msvs_version),
1186 'spec': spec,
1187 }
1188
1643 for project in project_objects.values():
1644 fixpath_prefix = project.fixpath_prefix
1645 _GenerateProject(project, options, msvs_version)
11891646 fixpath_prefix = None
11901647
1191 for build_file in data.keys():
1648 for build_file in data:
11921649 # Validate build_file extension
11931650 if build_file[-4:] != '.gyp':
11941651 continue
11951652 sln_path = build_file[:-4] + options.suffix + '.sln'
11961653 if options.generator_output:
11971654 sln_path = os.path.join(options.generator_output, sln_path)
1198 #print 'Generating %s' % sln_path
11991655 # Get projects in the solution, and their dependents.
12001656 sln_projects = gyp.common.BuildFileTargets(target_list, build_file)
12011657 sln_projects += gyp.common.DeepDependencyTargets(target_dicts, sln_projects)
1202 # Convert projects to Project Objects.
1203 project_objs = {}
1204 for p in sln_projects:
1205 _ProjectObject(sln_path, p, project_objs, projects)
12061658 # Create folder hierarchy.
12071659 root_entries = _GatherSolutionFolders(
1208 project_objs, flat=msvs_version.FlatSolution())
1660 sln_projects, project_objects, flat=msvs_version.FlatSolution())
12091661 # Create solution.
12101662 sln = MSVSNew.MSVSSolution(sln_path,
12111663 entries=root_entries,
12131665 websiteProperties=False,
12141666 version=msvs_version)
12151667 sln.Write()
1668
1669
1670 def _GenerateMSBuildFiltersFile(filters_path, source_files,
1671 extension_to_rule_name):
1672 """Generate the filters file.
1673
1674 This file is used by Visual Studio to organize the presentation of source
1675 files into folders.
1676
1677 Arguments:
1678 filters_path: The path of the file to be created.
1679 source_files: The hierarchical structure of all the sources.
1680 extension_to_rule_name: A dictionary mapping file extensions to rules.
1681 """
1682 filter_group = []
1683 source_group = []
1684 _AppendFiltersForMSBuild('', source_files, extension_to_rule_name,
1685 filter_group, source_group)
1686 if filter_group:
1687 doc = easy_xml.EasyXml(
1688 'Project',
1689 {'ToolsVersion': '4.0',
1690 'xmlns': 'http://schemas.microsoft.com/developer/msbuild/2003'})
1691 root = doc.Root()
1692 doc.AppendChildren(root, [
1693 ['ItemGroup'] + filter_group,
1694 ['ItemGroup'] + source_group])
1695 doc.WriteIfChanged(filters_path)
1696 elif os.path.exists(filters_path):
1697 # We don't need this filter anymore. Delete the old filter file.
1698 os.unlink(filters_path)
1699
1700
1701 def _AppendFiltersForMSBuild(parent_filter_name, sources,
1702 extension_to_rule_name,
1703 filter_group, source_group):
1704 """Creates the list of filters and sources to be added in the filter file.
1705
1706 Args:
1707 parent_filter_name: The name of the filter under which the sources are
1708 found.
1709 sources: The hierarchy of filters and sources to process.
1710 extension_to_rule_name: A dictionary mapping file extensions to rules.
1711 filter_group: The list to which filter entries will be appended.
1712 source_group: The list to which source entries will be appeneded.
1713 """
1714 for source in sources:
1715 if isinstance(source, MSVSProject.Filter):
1716 # We have a sub-filter. Create the name of that sub-filter.
1717 if not parent_filter_name:
1718 filter_name = source.name
1719 else:
1720 filter_name = '%s\\%s' % (parent_filter_name, source.name)
1721 # Add the filter to the group.
1722 filter_group.append(
1723 ['Filter', {'Include': filter_name},
1724 ['UniqueIdentifier', MSVSNew.MakeGuid(source.name)]])
1725 # Recurse and add its dependents.
1726 _AppendFiltersForMSBuild(filter_name, source.contents,
1727 extension_to_rule_name,
1728 filter_group, source_group)
1729 else:
1730 # It's a source. Create a source entry.
1731 _, element = _MapFileToMsBuildSourceType(source, extension_to_rule_name)
1732 source_entry = [element, {'Include': source}]
1733 # Specify the filter it is part of, if any.
1734 if parent_filter_name:
1735 source_entry.append(['Filter', parent_filter_name])
1736 source_group.append(source_entry)
1737
1738
1739 def _MapFileToMsBuildSourceType(source, extension_to_rule_name):
1740 """Returns the group and element type of the source file.
1741
1742 Arguments:
1743 source: The source file name.
1744 extension_to_rule_name: A dictionary mapping file extensions to rules.
1745
1746 Returns:
1747 A pair of (group this file should be part of, the label of element)
1748 """
1749 _, ext = os.path.splitext(source)
1750 if ext in ['.cc', '.cpp', '.c', '.cxx']:
1751 group = 'compile'
1752 element = 'ClCompile'
1753 elif ext in ['.h', '.hxx']:
1754 group = 'include'
1755 element = 'ClInclude'
1756 elif ext == '.rc':
1757 group = 'resource'
1758 element = 'ResourceCompile'
1759 elif ext == '.idl':
1760 group = 'midl'
1761 element = 'Midl'
1762 elif ext in extension_to_rule_name:
1763 group = 'rule'
1764 element = extension_to_rule_name[ext]
1765 else:
1766 group = 'none'
1767 element = 'None'
1768 return (group, element)
1769
1770
1771 def _GenerateRulesForMSBuild(output_dir, options, spec,
1772 sources, excluded_sources,
1773 props_files_of_rules, targets_files_of_rules,
1774 actions_to_add, extension_to_rule_name):
1775 # MSBuild rules are implemented using three files: an XML file, a .targets
1776 # file and a .props file.
1777 # See http://blogs.msdn.com/b/vcblog/archive/2010/04/21/quick-help-on-vs2010-custom-build-rule.aspx
1778 # for more details.
1779 rules = spec.get('rules', [])
1780 rules_native = [r for r in rules if not int(r.get('msvs_external_rule', 0))]
1781 rules_external = [r for r in rules if int(r.get('msvs_external_rule', 0))]
1782
1783 msbuild_rules = []
1784 for rule in rules_native:
1785 msbuild_rule = MSBuildRule(rule, spec)
1786 msbuild_rules.append(msbuild_rule)
1787 extension_to_rule_name[msbuild_rule.extension] = msbuild_rule.rule_name
1788 if msbuild_rules:
1789 base = spec['target_name'] + options.suffix
1790 props_name = base + '.props'
1791 targets_name = base + '.targets'
1792 xml_name = base + '.xml'
1793
1794 props_files_of_rules.add(props_name)
1795 targets_files_of_rules.add(targets_name)
1796
1797 props_path = os.path.join(output_dir, props_name)
1798 targets_path = os.path.join(output_dir, targets_name)
1799 xml_path = os.path.join(output_dir, xml_name)
1800
1801 _GenerateMSBuildRulePropsFile(props_path, msbuild_rules)
1802 _GenerateMSBuildRuleTargetsFile(targets_path, msbuild_rules)
1803 _GenerateMSBuildRuleXmlFile(xml_path, msbuild_rules)
1804
1805 if rules_external:
1806 _GenerateExternalRules(rules_external, output_dir, spec,
1807 sources, options, actions_to_add)
1808 _AdjustSourcesForRules(rules, sources, excluded_sources)
1809
1810
1811 class MSBuildRule(object):
1812 """Used to store information used to generate an MSBuild rule.
1813
1814 Attributes:
1815 rule_name: The rule name, sanitized to use in XML.
1816 target_name: The name of the target.
1817 after_targets: The name of the AfterTargets element.
1818 before_targets: The name of the BeforeTargets element.
1819 depends_on: The name of the DependsOn element.
1820 compute_output: The name of the ComputeOutput element.
1821 dirs_to_make: The name of the DirsToMake element.
1822 tlog: The name of the _tlog element.
1823 extension: The extension this rule applies to.
1824 description: The message displayed when this rule is invoked.
1825 additional_dependencies: A string listing additional dependencies.
1826 outputs: The outputs of this rule.
1827 command: The command used to run the rule.
1828 """
1829
1830 def __init__(self, rule, spec):
1831 self.display_name = rule['rule_name']
1832 # Assure that the rule name is only characters and numbers
1833 self.rule_name = re.sub(r'\W', '_', self.display_name)
1834 # Create the various element names, following the example set by the
1835 # Visual Studio 2008 to 2010 conversion. I don't know if VS2010
1836 # is sensitive to the exact names.
1837 self.target_name = '_' + self.rule_name
1838 self.after_targets = self.rule_name + 'AfterTargets'
1839 self.before_targets = self.rule_name + 'BeforeTargets'
1840 self.depends_on = self.rule_name + 'DependsOn'
1841 self.compute_output = 'Compute%sOutput' % self.rule_name
1842 self.dirs_to_make = self.rule_name + 'DirsToMake'
1843 self.tlog = self.rule_name + '_tlog'
1844 self.extension = rule['extension']
1845 if not self.extension.startswith('.'):
1846 self.extension = '.' + self.extension
1847
1848 self.description = MSVSSettings.ConvertVCMacrosToMSBuild(
1849 rule.get('message', self.rule_name))
1850 old_additional_dependencies = _FixPaths(rule.get('inputs', []))
1851 self.additional_dependencies = (
1852 ';'.join([MSVSSettings.ConvertVCMacrosToMSBuild(i)
1853 for i in old_additional_dependencies]))
1854 old_outputs = _FixPaths(rule.get('outputs', []))
1855 self.outputs = ';'.join([MSVSSettings.ConvertVCMacrosToMSBuild(i)
1856 for i in old_outputs])
1857 old_command = _BuildCommandLineForRule(spec, rule, has_input_path=True)
1858 self.command = MSVSSettings.ConvertVCMacrosToMSBuild(old_command)
1859
1860
1861 def _GenerateMSBuildRulePropsFile(props_path, msbuild_rules):
1862 """Generate the .props file."""
1863 doc = easy_xml.EasyXml(
1864 'Project',
1865 {'xmlns': 'http://schemas.microsoft.com/developer/msbuild/2003'})
1866 root = doc.Root()
1867 for rule in msbuild_rules:
1868 doc.AppendChildren(root, [
1869 ['PropertyGroup',
1870 {'Condition': "'$(%s)' == '' and '$(%s)' == '' and "
1871 "'$(ConfigurationType)' != 'Makefile'" % (rule.before_targets,
1872 rule.after_targets)
1873 },
1874 [rule.before_targets, 'Midl'],
1875 [rule.after_targets, 'CustomBuild'],
1876 ],
1877 ['PropertyGroup',
1878 [rule.depends_on,
1879 {'Condition': "'$(ConfigurationType)' != 'Makefile'"},
1880 '_SelectedFiles;$(%s)' % rule.depends_on
1881 ],
1882 ],
1883 ['ItemDefinitionGroup',
1884 [rule.rule_name,
1885 ['CommandLineTemplate', rule.command],
1886 ['Outputs', rule.outputs],
1887 ['ExecutionDescription', rule.description],
1888 ['AdditionalDependencies', rule.additional_dependencies],
1889 ],
1890 ]
1891 ])
1892 doc.WriteIfChanged(props_path)
1893
1894
1895 def _GenerateMSBuildRuleTargetsFile(targets_path, msbuild_rules):
1896 """Generate the .targets file."""
1897 doc = easy_xml.EasyXml(
1898 'Project',
1899 {'xmlns': 'http://schemas.microsoft.com/developer/msbuild/2003'})
1900 root = doc.Root()
1901 item_group = doc.AppendNode(
1902 root,
1903 ['ItemGroup',
1904 ['PropertyPageSchema',
1905 {'Include': '$(MSBuildThisFileDirectory)$(MSBuildThisFileName).xml'}
1906 ],
1907 ])
1908 for rule in msbuild_rules:
1909 doc.AppendNode(
1910 item_group,
1911 ['AvailableItemName',
1912 {'Include': rule.rule_name},
1913 ['Targets', rule.target_name],
1914 ])
1915 for rule in msbuild_rules:
1916 doc.AppendNode(
1917 root,
1918 ['UsingTask',
1919 {'TaskName': rule.rule_name,
1920 'TaskFactory': 'XamlTaskFactory',
1921 'AssemblyName': 'Microsoft.Build.Tasks.v4.0'
1922 },
1923 ['Task', '$(MSBuildThisFileDirectory)$(MSBuildThisFileName).xml'],
1924 ])
1925 for rule in msbuild_rules:
1926 rule_name = rule.rule_name
1927 target_outputs = '%%(%s.Outputs)' % rule_name
1928 target_inputs = ('%%(%s.Identity);%%(%s.AdditionalDependencies);'
1929 '$(MSBuildProjectFile)') % (rule_name, rule_name)
1930 rule_inputs = '%%(%s.Identity)' % rule_name
1931 extension_condition = ("'%(Extension)'=='.obj' or "
1932 "'%(Extension)'=='.res' or "
1933 "'%(Extension)'=='.rsc' or "
1934 "'%(Extension)'=='.lib'")
1935 remove_section = [
1936 'ItemGroup',
1937 {'Condition': "'@(SelectedFiles)' != ''"},
1938 [rule_name,
1939 {'Remove': '@(%s)' % rule_name,
1940 'Condition': "'%(Identity)' != '@(SelectedFiles)'"
1941 }
1942 ]
1943 ]
1944 logging_section = [
1945 'ItemGroup',
1946 [rule.tlog,
1947 {'Include': '%%(%s.Outputs)' % rule_name,
1948 'Condition': ("'%%(%s.Outputs)' != '' and "
1949 "'%%(%s.ExcludedFromBuild)' != 'true'" %
1950 (rule_name, rule_name))
1951 },
1952 ['Source', "@(%s, '|')" % rule_name],
1953 ],
1954 ]
1955 message_section = [
1956 'Message',
1957 {'Importance': 'High',
1958 'Text': '%%(%s.ExecutionDescription)' % rule_name
1959 }
1960 ]
1961 write_lines_section = [
1962 'WriteLinesToFile',
1963 {'Condition': "'@(%s)' != '' and '%%(%s.ExcludedFromBuild)' != "
1964 "'true'" % (rule.tlog, rule.tlog),
1965 'File': '$(IntDir)$(ProjectName).write.1.tlog',
1966 'Lines': "^%%(%s.Source);@(%s->'%%(Fullpath)')" % (rule.tlog,
1967 rule.tlog)
1968 }
1969 ]
1970 command_and_input_section = [
1971 rule_name,
1972 {'Condition': "'@(%s)' != '' and '%%(%s.ExcludedFromBuild)' != "
1973 "'true'" % (rule_name, rule_name),
1974 'CommandLineTemplate': '%%(%s.CommandLineTemplate)' % rule_name,
1975 'AdditionalOptions': '%%(%s.AdditionalOptions)' % rule_name,
1976 'Inputs': rule_inputs
1977 }
1978 ]
1979 doc.AppendChildren(root, [
1980 ['Target',
1981 {'Name': rule.target_name,
1982 'BeforeTargets': '$(%s)' % rule.before_targets,
1983 'AfterTargets': '$(%s)' % rule.after_targets,
1984 'Condition': "'@(%s)' != ''" % rule_name,
1985 'DependsOnTargets': '$(%s);%s' % (rule.depends_on,
1986 rule.compute_output),
1987 'Outputs': target_outputs,
1988 'Inputs': target_inputs
1989 },
1990 remove_section,
1991 logging_section,
1992 message_section,
1993 write_lines_section,
1994 command_and_input_section,
1995 ],
1996 ['PropertyGroup',
1997 ['ComputeLinkInputsTargets',
1998 '$(ComputeLinkInputsTargets);',
1999 '%s;' % rule.compute_output
2000 ],
2001 ['ComputeLibInputsTargets',
2002 '$(ComputeLibInputsTargets);',
2003 '%s;' % rule.compute_output
2004 ],
2005 ],
2006 ['Target',
2007 {'Name': rule.compute_output,
2008 'Condition': "'@(%s)' != ''" % rule_name
2009 },
2010 ['ItemGroup',
2011 [rule.dirs_to_make,
2012 {'Condition': "'@(%s)' != '' and "
2013 "'%%(%s.ExcludedFromBuild)' != 'true'" % (rule_name, rule_name),
2014 'Include': '%%(%s.Outputs)' % rule_name
2015 }
2016 ],
2017 ['Link',
2018 {'Include': '%%(%s.Identity)' % rule.dirs_to_make,
2019 'Condition': extension_condition
2020 }
2021 ],
2022 ['Lib',
2023 {'Include': '%%(%s.Identity)' % rule.dirs_to_make,
2024 'Condition': extension_condition
2025 }
2026 ],
2027 ['ImpLib',
2028 {'Include': '%%(%s.Identity)' % rule.dirs_to_make,
2029 'Condition': extension_condition
2030 }
2031 ],
2032 ],
2033 ['MakeDir',
2034 {'Directories': ("@(%s->'%%(RootDir)%%(Directory)')" %
2035 rule.dirs_to_make)
2036 }
2037 ]
2038 ],
2039 ])
2040 doc.WriteIfChanged(targets_path)
2041
2042
2043 def _GenerateMSBuildRuleXmlFile(xml_path, msbuild_rules):
2044 # Generate the .xml file
2045 doc = easy_xml.EasyXml(
2046 'ProjectSchemaDefinitions',
2047 {'xmlns': ('clr-namespace:Microsoft.Build.Framework.XamlTypes;'
2048 'assembly=Microsoft.Build.Framework'),
2049 'xmlns:x': 'http://schemas.microsoft.com/winfx/2006/xaml',
2050 'xmlns:sys': 'clr-namespace:System;assembly=mscorlib',
2051 'xmlns:transformCallback':
2052 'Microsoft.Cpp.Dev10.ConvertPropertyCallback'})
2053 root = doc.Root()
2054 for rule in msbuild_rules:
2055 doc.AppendChildren(root, [
2056 ['Rule',
2057 {'Name': rule.rule_name,
2058 'PageTemplate': 'tool',
2059 'DisplayName': rule.display_name,
2060 'Order': '200'
2061 },
2062 ['Rule.DataSource',
2063 ['DataSource',
2064 {'Persistence': 'ProjectFile',
2065 'ItemType': rule.rule_name
2066 }
2067 ]
2068 ],
2069 ['Rule.Categories',
2070 ['Category',
2071 {'Name': 'General'},
2072 ['Category.DisplayName',
2073 ['sys:String', 'General'],
2074 ],
2075 ],
2076 ['Category',
2077 {'Name': 'Command Line',
2078 'Subtype': 'CommandLine'
2079 },
2080 ['Category.DisplayName',
2081 ['sys:String', 'Command Line'],
2082 ],
2083 ],
2084 ],
2085 ['StringListProperty',
2086 {'Name': 'Inputs',
2087 'Category': 'Command Line',
2088 'IsRequired': 'true',
2089 'Switch': ' '
2090 },
2091 ['StringListProperty.DataSource',
2092 ['DataSource',
2093 {'Persistence': 'ProjectFile',
2094 'ItemType': rule.rule_name,
2095 'SourceType': 'Item'
2096 }
2097 ]
2098 ],
2099 ],
2100 ['StringProperty',
2101 {'Name': 'CommandLineTemplate',
2102 'DisplayName': 'Command Line',
2103 'Visible': 'False',
2104 'IncludeInCommandLine': 'False'
2105 }
2106 ],
2107 ['DynamicEnumProperty',
2108 {'Name': rule.before_targets,
2109 'Category': 'General',
2110 'EnumProvider': 'Targets',
2111 'IncludeInCommandLine': 'False'
2112 },
2113 ['DynamicEnumProperty.DisplayName',
2114 ['sys:String', 'Execute Before'],
2115 ],
2116 ['DynamicEnumProperty.Description',
2117 ['sys:String', 'Specifies the targets for the build customization'
2118 ' to run before.'
2119 ],
2120 ],
2121 ['DynamicEnumProperty.ProviderSettings',
2122 ['NameValuePair',
2123 {'Name': 'Exclude',
2124 'Value': '^%s|^Compute' % rule.before_targets
2125 }
2126 ]
2127 ],
2128 ['DynamicEnumProperty.DataSource',
2129 ['DataSource',
2130 {'Persistence': 'ProjectFile',
2131 'HasConfigurationCondition': 'true'
2132 }
2133 ]
2134 ],
2135 ],
2136 ['DynamicEnumProperty',
2137 {'Name': rule.after_targets,
2138 'Category': 'General',
2139 'EnumProvider': 'Targets',
2140 'IncludeInCommandLine': 'False'
2141 },
2142 ['DynamicEnumProperty.DisplayName',
2143 ['sys:String', 'Execute After'],
2144 ],
2145 ['DynamicEnumProperty.Description',
2146 ['sys:String', ('Specifies the targets for the build customization'
2147 ' to run after.')
2148 ],
2149 ],
2150 ['DynamicEnumProperty.ProviderSettings',
2151 ['NameValuePair',
2152 {'Name': 'Exclude',
2153 'Value': '^%s|^Compute' % rule.after_targets
2154 }
2155 ]
2156 ],
2157 ['DynamicEnumProperty.DataSource',
2158 ['DataSource',
2159 {'Persistence': 'ProjectFile',
2160 'ItemType': '',
2161 'HasConfigurationCondition': 'true'
2162 }
2163 ]
2164 ],
2165 ],
2166 ['StringListProperty',
2167 {'Name': 'Outputs',
2168 'DisplayName': 'Outputs',
2169 'Visible': 'False',
2170 'IncludeInCommandLine': 'False'
2171 }
2172 ],
2173 ['StringProperty',
2174 {'Name': 'ExecutionDescription',
2175 'DisplayName': 'Execution Description',
2176 'Visible': 'False',
2177 'IncludeInCommandLine': 'False'
2178 }
2179 ],
2180 ['StringListProperty',
2181 {'Name': 'AdditionalDependencies',
2182 'DisplayName': 'Additional Dependencies',
2183 'IncludeInCommandLine': 'False',
2184 'Visible': 'false'
2185 }
2186 ],
2187 ['StringProperty',
2188 {'Subtype': 'AdditionalOptions',
2189 'Name': 'AdditionalOptions',
2190 'Category': 'Command Line'
2191 },
2192 ['StringProperty.DisplayName',
2193 ['sys:String', 'Additional Options'],
2194 ],
2195 ['StringProperty.Description',
2196 ['sys:String', 'Additional Options'],
2197 ],
2198 ],
2199 ],
2200 ['ItemType',
2201 {'Name': rule.rule_name,
2202 'DisplayName': rule.display_name
2203 }
2204 ],
2205 ['FileExtension',
2206 {'Name': '*' + rule.extension,
2207 'ContentType': rule.rule_name
2208 }
2209 ],
2210 ['ContentType',
2211 {'Name': rule.rule_name,
2212 'DisplayName': '',
2213 'ItemType': rule.rule_name
2214 }
2215 ]
2216 ])
2217 doc.WriteIfChanged(xml_path)
2218
2219
2220 def _GetConfigurationAndPlatform(name, settings):
2221 configuration = name.rsplit('_', 1)[0]
2222 platform = settings.get('msvs_configuration_platform', 'Win32')
2223 return (configuration, platform)
2224
2225
2226 def _GetConfigurationCondition(name, settings):
2227 return (r"'$(Configuration)|$(Platform)'=='%s|%s'" %
2228 _GetConfigurationAndPlatform(name, settings))
2229
2230
2231 def _GetMSBuildProjectConfigurations(configurations):
2232 group = ['ItemGroup', {'Label': 'ProjectConfigurations'}]
2233 for (name, settings) in sorted(configurations.iteritems()):
2234 configuration, platform = _GetConfigurationAndPlatform(name, settings)
2235 designation = '%s|%s' % (configuration, platform)
2236 group.append(
2237 ['ProjectConfiguration', {'Include': designation},
2238 ['Configuration', configuration],
2239 ['Platform', platform]])
2240 return [group]
2241
2242
2243 def _GetMSBuildGlobalProperties(spec, guid, gyp_file_name):
2244 prefix = spec.get('product_prefix', '')
2245 product_name = spec.get('product_name', '$(ProjectName)')
2246 target_name = prefix + product_name
2247 namespace = os.path.splitext(gyp_file_name)[0]
2248 return [
2249 ['PropertyGroup', {'Label': 'Globals'},
2250 ['ProjectGuid', guid],
2251 ['Keyword', 'Win32Proj'],
2252 ['RootNamespace', namespace],
2253 ['TargetName', target_name],
2254 ]
2255 ]
2256
2257
2258 def _GetMSBuildConfigurationDetails(spec, build_file):
2259 groups = []
2260 for (name, settings) in sorted(spec['configurations'].iteritems()):
2261 msbuild_attributes = _GetMSBuildAttributes(spec, settings, build_file)
2262 group = ['PropertyGroup',
2263 {'Condition': _GetConfigurationCondition(name, settings),
2264 'Label': 'Configuration'},
2265 ['ConfigurationType', msbuild_attributes['ConfigurationType']]]
2266 if 'CharacterSet' in msbuild_attributes:
2267 group.append(['CharacterSet', msbuild_attributes['CharacterSet']])
2268 groups.append(group)
2269 return groups
2270
2271
2272 def _GetMSBuildPropertySheets(configurations):
2273 sheets = []
2274 for (name, settings) in sorted(configurations.iteritems()):
2275 user_props = r'$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props'
2276 sheets.append(
2277 ['ImportGroup',
2278 {'Label': 'PropertySheets',
2279 'Condition': _GetConfigurationCondition(name, settings)
2280 },
2281 ['Import',
2282 {'Project': user_props,
2283 'Condition': "exists('%s')" % user_props,
2284 'Label': 'LocalAppDataPlatform'
2285 }
2286 ]
2287 ])
2288 return sheets
2289
2290
2291 def _GetMSBuildAttributes(spec, config, build_file):
2292 # Use the MSVS attributes and convert them. In the future, we may want to
2293 # support Gyp files specifying 'msbuild_configuration_attributes' directly.
2294 config_type = _GetMSVSConfigurationType(spec, build_file)
2295 msvs_attributes = _GetMSVSAttributes(spec, config, config_type)
2296 msbuild_attributes = {}
2297 for a in msvs_attributes:
2298 if a in ['IntermediateDirectory', 'OutputDirectory']:
2299 directory = MSVSSettings.ConvertVCMacrosToMSBuild(msvs_attributes[a])
2300 if not directory.endswith('\\'):
2301 directory += '\\'
2302 msbuild_attributes[a] = directory
2303 elif a == 'CharacterSet':
2304 msbuild_attributes[a] = {
2305 '0': 'MultiByte',
2306 '1': 'Unicode'
2307 }[msvs_attributes[a]]
2308 elif a == 'ConfigurationType':
2309 msbuild_attributes[a] = {
2310 '1': 'Application',
2311 '2': 'DynamicLibrary',
2312 '4': 'StaticLibrary',
2313 '10': 'Utility'
2314 }[msvs_attributes[a]]
2315 else:
2316 print 'Warning: Do not know how to convert MSVS attribute ' + a
2317 return msbuild_attributes
2318
2319
2320 def _GetMSBuildConfigurationGlobalProperties(spec, configurations, build_file):
2321 group = ['PropertyGroup']
2322 for (name, configuration) in sorted(configurations.iteritems()):
2323 condition = _GetConfigurationCondition(name, configuration)
2324 attributes = _GetMSBuildAttributes(spec, configuration, build_file)
2325 msbuild_settings = configuration['finalized_msbuild_settings']
2326 group.extend(
2327 [['IntDir',
2328 {'Condition': condition},
2329 attributes['IntermediateDirectory']
2330 ],
2331 ['OutDir',
2332 {'Condition': condition},
2333 attributes['OutputDirectory']
2334 ],
2335 ])
2336 # TODO(jeanluc) We could optimize out the following and do it only if
2337 # there are actions.
2338 # TODO(jeanluc) Handle the equivalent of setting 'CYGWIN=nontsec'.
2339 new_paths = []
2340 cygwin_dirs = spec.get('msvs_cygwin_dirs', ['.'])[0]
2341 if cygwin_dirs:
2342 cyg_path = '$(MSBuildProjectDirectory)\\%s\\bin\\' % _FixPath(cygwin_dirs)
2343 new_paths.append(cyg_path)
2344 # TODO(jeanluc) Change the convention to have both a cygwin_dir and a
2345 # python_dir.
2346 python_path = cyg_path.replace('cygwin\\bin', 'python_26')
2347 new_paths.append(python_path)
2348 if new_paths:
2349 group.append(['ExecutablePath', {'Condition': condition},
2350 '$(ExecutablePath);' + ';'.join(new_paths)])
2351 tool_settings = msbuild_settings.get('', {})
2352 for name, value in sorted(tool_settings.iteritems()):
2353 formatted_value = _GetValueFormattedForMSBuild('', name, value)
2354 group.append([name, {'Condition': condition}, formatted_value])
2355 return [group]
2356
2357
2358 def _GetMSBuildToolSettingsSections(spec, configurations):
2359 groups = []
2360 for (name, configuration) in sorted(configurations.iteritems()):
2361 msbuild_settings = configuration['finalized_msbuild_settings']
2362 group = ['ItemDefinitionGroup',
2363 {'Condition': _GetConfigurationCondition(name, configuration)}
2364 ]
2365 for tool_name, tool_settings in sorted(msbuild_settings.iteritems()):
2366 # Skip the tool named '' which is a holder of global settings handled
2367 # by _GetMSBuildConfigurationGlobalProperties.
2368 if tool_name:
2369 if tool_settings:
2370 tool = [tool_name]
2371 for name, value in sorted(tool_settings.iteritems()):
2372 formatted_value = _GetValueFormattedForMSBuild(tool_name, name,
2373 value)
2374 tool.append([name, formatted_value])
2375 group.append(tool)
2376 groups.append(group)
2377 return groups
2378
2379
2380 def _FinalizeMSBuildSettings(spec, configuration):
2381 if 'msbuild_settings' in configuration:
2382 converted = False
2383 msbuild_settings = configuration['msbuild_settings']
2384 MSVSSettings.ValidateMSBuildSettings(msbuild_settings)
2385 else:
2386 converted = True
2387 msvs_settings = configuration.get('msvs_settings', {})
2388 msbuild_settings = MSVSSettings.ConvertToMSBuildSettings(msvs_settings)
2389 include_dirs, resource_include_dirs = _GetIncludeDirs(configuration)
2390 libraries = _GetLibraries(spec)
2391 out_file, _, msbuild_tool = _GetOutputFilePathAndTool(spec)
2392 defines = _GetDefines(configuration)
2393 if converted:
2394 # Visual Studio 2010 has TR1
2395 defines = [d for d in defines if d != '_HAS_TR1=0']
2396 # Warn of ignored settings
2397 ignored_settings = ['msvs_prebuild', 'msvs_postbuild', 'msvs_tool_files']
2398 for ignored_setting in ignored_settings:
2399 value = configuration.get(ignored_setting)
2400 if value:
2401 print ('Warning: The automatic conversion to MSBuild does not handle '
2402 '%s. Ignoring setting of %s' % (ignored_setting, str(value)))
2403
2404 defines = [_EscapeCppDefineForMSBuild(d) for d in defines]
2405 disabled_warnings = _GetDisabledWarnings(configuration)
2406 # TODO(jeanluc) Validate & warn that we don't translate
2407 # prebuild = configuration.get('msvs_prebuild')
2408 # postbuild = configuration.get('msvs_postbuild')
2409 def_file = _GetModuleDefinition(spec)
2410 precompiled_header = configuration.get('msvs_precompiled_header')
2411
2412 # Add the information to the appropriate tool
2413 # TODO(jeanluc) We could optimize and generate these settings only if
2414 # the corresponding files are found, e.g. don't generate ResourceCompile
2415 # if you don't have any resources.
2416 _ToolAppend(msbuild_settings, 'ClCompile',
2417 'AdditionalIncludeDirectories', include_dirs)
2418 _ToolAppend(msbuild_settings, 'ResourceCompile',
2419 'AdditionalIncludeDirectories', resource_include_dirs)
2420 # Add in libraries.
2421 _ToolAppend(msbuild_settings, 'Link', 'AdditionalDependencies', libraries)
2422 if out_file:
2423 _ToolAppend(msbuild_settings, msbuild_tool, 'OutputFile', out_file,
2424 only_if_unset=True)
2425 # Add defines.
2426 _ToolAppend(msbuild_settings, 'ClCompile',
2427 'PreprocessorDefinitions', defines)
2428 _ToolAppend(msbuild_settings, 'ResourceCompile',
2429 'PreprocessorDefinitions', defines)
2430 # Add disabled warnings.
2431 _ToolAppend(msbuild_settings, 'ClCompile',
2432 'DisableSpecificWarnings', disabled_warnings)
2433 # Turn on precompiled headers if appropriate.
2434 if precompiled_header:
2435 precompiled_header = os.path.split(precompiled_header)[1]
2436 _ToolAppend(msbuild_settings, 'ClCompile', 'PrecompiledHeader', 'Use')
2437 _ToolAppend(msbuild_settings, 'ClCompile',
2438 'PrecompiledHeaderFile', precompiled_header)
2439 _ToolAppend(msbuild_settings, 'ClCompile',
2440 'ForcedIncludeFiles', precompiled_header)
2441 # Loadable modules don't generate import libraries;
2442 # tell dependent projects to not expect one.
2443 if spec['type'] == 'loadable_module':
2444 _ToolAppend(msbuild_settings, '', 'IgnoreImportLibrary', 'true')
2445 # Set the module definition file if any.
2446 if def_file:
2447 _ToolAppend(msbuild_settings, 'Link', 'ModuleDefinitionFile', def_file)
2448 configuration['finalized_msbuild_settings'] = msbuild_settings
2449
2450
2451 def _GetValueFormattedForMSBuild(tool_name, name, value):
2452 if type(value) == list:
2453 # For some settings, VS2010 does not automatically extends the settings
2454 # TODO(jeanluc) Is this what we want?
2455 if name in ['AdditionalDependencies',
2456 'AdditionalIncludeDirectories',
2457 'AdditionalLibraryDirectories',
2458 'AdditionalOptions',
2459 'DelayLoadDLLs',
2460 'DisableSpecificWarnings',
2461 'PreprocessorDefinitions']:
2462 value.append('%%(%s)' % name)
2463 # TODO(jeanluc) Not all of them need to be fixed, why?
2464 if name in ['AdditionalIncludeDirectories', 'AdditionalLibraryDirectories']:
2465 value = _FixPaths(value)
2466 # For most tools, entries in a list should be separated with ';' but some
2467 # settings use a space. Check for those first.
2468 exceptions = {
2469 'ClCompile': ['AdditionalOptions'],
2470 'Link': ['AdditionalOptions'],
2471 'Lib': ['AdditionalOptions']}
2472 if tool_name in exceptions and name in exceptions[tool_name]:
2473 char = ' '
2474 else:
2475 char = ';'
2476 formatted_value = char.join(
2477 [MSVSSettings.ConvertVCMacrosToMSBuild(i) for i in value])
2478 else:
2479 formatted_value = MSVSSettings.ConvertVCMacrosToMSBuild(value)
2480 return formatted_value
2481
2482
2483 def _GetMSBuildSources(spec, root_dir, sources, exclusions,
2484 extension_to_rule_name, actions_spec,
2485 sources_handled_by_action):
2486 groups = ['none', 'midl', 'include', 'compile', 'resource', 'rule']
2487 grouped_sources = {}
2488 for g in groups:
2489 grouped_sources[g] = []
2490
2491 _AddSources2(spec, root_dir, sources, exclusions, grouped_sources,
2492 extension_to_rule_name, sources_handled_by_action)
2493 sources = []
2494 for g in groups:
2495 if grouped_sources[g]:
2496 sources.append(['ItemGroup'] + grouped_sources[g])
2497 if actions_spec:
2498 sources.append(['ItemGroup'] + actions_spec)
2499 return sources
2500
2501
2502 def _AddSources2(spec, root_dir, sources, exclusions, grouped_sources,
2503 extension_to_rule_name, sources_handled_by_action):
2504 for source in sources:
2505 if isinstance(source, MSVSProject.Filter):
2506 _AddSources2(spec, root_dir, source.contents, exclusions, grouped_sources,
2507 extension_to_rule_name, sources_handled_by_action)
2508 else:
2509 # If it is a regular source file, i.e. not created at run time,
2510 # warn if it does not exists. Missing header files will cause needless
2511 # but no otherwise visible errors.
2512 if '$' not in source:
2513 full_path = os.path.join(root_dir, source)
2514 if not os.path.exists(full_path):
2515 print 'Warning: Missing input file ' + full_path
2516 if not source in sources_handled_by_action:
2517 detail = []
2518 for config_name, configuration in sorted(exclusions.get(source, [])):
2519 condition = _GetConfigurationCondition(config_name, configuration)
2520 detail.append(['ExcludedFromBuild', {'Condition': condition}, 'true'])
2521 # Add precompile if needed
2522 for config_name, configuration in spec['configurations'].iteritems():
2523 precompiled_source = configuration.get('msvs_precompiled_source', '')
2524 precompiled_source = _FixPath(precompiled_source)
2525 if precompiled_source == source:
2526 condition = _GetConfigurationCondition(config_name, configuration)
2527 detail.append(['PrecompiledHeader',
2528 {'Condition': condition},
2529 'Create'
2530 ])
2531 group, element = _MapFileToMsBuildSourceType(source,
2532 extension_to_rule_name)
2533 grouped_sources[group].append([element, {'Include': source}] + detail)
2534
2535
2536 def _GetMSBuildProjectReferences(project):
2537 references = []
2538 if project.dependencies:
2539 group = ['ItemGroup']
2540 for dependency in project.dependencies:
2541 guid = dependency.guid
2542 project_dir = os.path.split(project.path)[0]
2543 relative_path = gyp.common.RelativePath(dependency.path, project_dir)
2544 group.append(
2545 ['ProjectReference',
2546 {'Include': relative_path},
2547 ['Project', guid],
2548 ['ReferenceOutputAssembly', 'false']
2549 ])
2550 references.append(group)
2551 return references
2552
2553
2554 def _GenerateMSBuildProject(project, options, version):
2555 spec = project.spec
2556 configurations = spec['configurations']
2557 gyp_dir, gyp_file_name = os.path.split(project.path)
2558 msbuildproj_dir = os.path.dirname(project.path)
2559 if msbuildproj_dir and not os.path.exists(msbuildproj_dir):
2560 os.makedirs(msbuildproj_dir)
2561 # Prepare list of sources and excluded sources.
2562 gyp_dir = os.path.split(project.path)[0]
2563 gyp_file = posixpath.split(project.build_file)[1]
2564 gyp_path = _NormalizedSource(gyp_file)
2565 relative_path_of_gyp_file = gyp.common.RelativePath(gyp_path, gyp_dir)
2566
2567 sources, excluded_sources = _PrepareListOfSources(spec,
2568 relative_path_of_gyp_file)
2569 # Add rules.
2570 actions_to_add = {}
2571 props_files_of_rules = set()
2572 targets_files_of_rules = set()
2573 extension_to_rule_name = {}
2574 _GenerateRulesForMSBuild(gyp_dir, options, spec,
2575 sources, excluded_sources,
2576 props_files_of_rules, targets_files_of_rules,
2577 actions_to_add, extension_to_rule_name)
2578 sources, excluded_sources, excluded_idl = (
2579 _AdjustSourcesAndConvertToFilterHierarchy(spec, options,
2580 gyp_dir, sources,
2581 excluded_sources))
2582 _AddActions(actions_to_add, spec, project.build_file)
2583 _AddCopies(actions_to_add, spec)
2584
2585 # NOTE: this stanza must appear after all actions have been decided.
2586 # Don't excluded sources with actions attached, or they won't run.
2587 excluded_sources = _FilterActionsFromExcluded(
2588 excluded_sources, actions_to_add)
2589
2590 exclusions = _GetExcludedFilesFromBuild(spec, excluded_sources, excluded_idl)
2591 actions_spec, sources_handled_by_action = _GenerateActionsForMSBuild(
2592 spec, actions_to_add)
2593
2594 _GenerateMSBuildFiltersFile(project.path + '.filters', sources,
2595 extension_to_rule_name)
2596
2597 for (_, configuration) in configurations.iteritems():
2598 _FinalizeMSBuildSettings(spec, configuration)
2599
2600 # Add attributes to root element
2601
2602 doc = easy_xml.EasyXml(
2603 'Project',
2604 {'xmlns': 'http://schemas.microsoft.com/developer/msbuild/2003',
2605 'ToolsVersion': version.ProjectVersion(),
2606 'DefaultTargets': 'Build'
2607 })
2608
2609 import_default_section = [
2610 ['Import', {'Project': r'$(VCTargetsPath)\Microsoft.Cpp.Default.props'}]]
2611 import_cpp_props_section = [
2612 ['Import', {'Project': r'$(VCTargetsPath)\Microsoft.Cpp.props'}]]
2613 import_cpp_targets_section = [
2614 ['Import', {'Project': r'$(VCTargetsPath)\Microsoft.Cpp.targets'}]]
2615 macro_section = [['PropertyGroup', {'Label': 'UserMacros'}]]
2616
2617 content = _GetMSBuildProjectConfigurations(configurations)
2618 content += _GetMSBuildGlobalProperties(spec, project.guid, gyp_file_name)
2619 content += import_default_section
2620 content += _GetMSBuildConfigurationDetails(spec, project.build_file)
2621 content += import_cpp_props_section
2622 content += _GetMSBuildExtensions(props_files_of_rules)
2623 content += _GetMSBuildPropertySheets(configurations)
2624 content += macro_section
2625 content += _GetMSBuildConfigurationGlobalProperties(spec, configurations,
2626 project.build_file)
2627 content += _GetMSBuildToolSettingsSections(spec, configurations)
2628 content += _GetMSBuildSources(
2629 spec, gyp_dir, sources, exclusions, extension_to_rule_name, actions_spec,
2630 sources_handled_by_action)
2631 content += _GetMSBuildProjectReferences(project)
2632 content += import_cpp_targets_section
2633 content += _GetMSBuildExtensionTargets(targets_files_of_rules)
2634
2635 # TODO(jeanluc) File a bug to get rid of runas. We had in MSVS:
2636 # has_run_as = _WriteMSVSUserFile(project.path, version, spec)
2637
2638 doc.AppendChildren(doc.Root(), content)
2639 doc.WriteIfChanged(project.path)
2640
2641
2642 def _GetMSBuildExtensions(props_files_of_rules):
2643 extensions = ['ImportGroup', {'Label': 'ExtensionSettings'}]
2644 for props_file in props_files_of_rules:
2645 extensions.append(['Import', {'Project': props_file}])
2646 return [extensions]
2647
2648
2649 def _GetMSBuildExtensionTargets(targets_files_of_rules):
2650 targets_node = ['ImportGroup', {'Label': 'ExtensionTargets'}]
2651 for targets_file in sorted(targets_files_of_rules):
2652 targets_node.append(['Import', {'Project': targets_file}])
2653 return [targets_node]
2654
2655
2656 def _GenerateActionsForMSBuild(spec, actions_to_add):
2657 """Add actions accumulated into an actions_to_add, merging as needed.
2658
2659 Arguments:
2660 spec: the target project dict
2661 actions_to_add: dictionary keyed on input name, which maps to a list of
2662 dicts describing the actions attached to that input file.
2663
2664 Returns:
2665 A pair of (action specification, the sources handled by this action).
2666 """
2667 sources_handled_by_action = set()
2668 actions_spec = []
2669 for primary_input, actions in actions_to_add.iteritems():
2670 inputs = set()
2671 outputs = set()
2672 descriptions = []
2673 commands = []
2674 for action in actions:
2675 inputs.update(set(action['inputs']))
2676 outputs.update(set(action['outputs']))
2677 descriptions.append(action['description'])
2678 cmd = action['command']
2679 # For most actions, add 'call' so that actions that invoke batch files
2680 # return and continue executing. msbuild_use_call provides a way to
2681 # disable this but I have not seen any adverse effect from doing that
2682 # for everything.
2683 if action.get('msbuild_use_call', True):
2684 cmd = 'call ' + cmd
2685 commands.append(cmd)
2686 # Add the custom build action for one input file.
2687 description = ', and also '.join(descriptions)
2688 command = ' && '.join(commands)
2689 _AddMSBuildAction(spec,
2690 primary_input,
2691 inputs,
2692 outputs,
2693 command,
2694 description,
2695 sources_handled_by_action,
2696 actions_spec)
2697 return actions_spec, sources_handled_by_action
2698
2699
2700 def _AddMSBuildAction(spec, primary_input, inputs, outputs, cmd, description,
2701 sources_handled_by_action, actions_spec):
2702 command = MSVSSettings.ConvertVCMacrosToMSBuild(cmd)
2703 primary_input = _FixPath(primary_input)
2704 inputs_array = _FixPaths(inputs)
2705 outputs_array = _FixPaths(outputs)
2706 additional_inputs = ';'.join([i for i in inputs_array
2707 if i != primary_input])
2708 outputs = ';'.join(outputs_array)
2709 sources_handled_by_action.add(primary_input)
2710 action_spec = ['CustomBuild', {'Include': primary_input}]
2711 for name, configuration in spec['configurations'].iteritems():
2712 condition_clause = {
2713 'Condition':
2714 _GetConfigurationCondition(name, configuration)
2715 }
2716 action_spec.extend(
2717 # TODO(jeanluc) 'Document' for all or just if as_sources?
2718 [['FileType', 'Document'],
2719 ['Command', condition_clause, command],
2720 ['Message', condition_clause, description],
2721 ['Outputs', condition_clause, outputs]
2722 ])
2723 if additional_inputs:
2724 action_spec.append(['AdditionalInputs', condition_clause,
2725 additional_inputs])
2726 actions_spec.append(action_spec)
529529 fp.write(fmt % (repr(dest), repr(f)))
530530 fp.write('target_files.extend(_outputs)\n')
531531
532 if spec.get('run_as') or int(spec.get('test', 0)):
533 run_as = spec.get('run_as', {
534 'action' : ['$TARGET_NAME', '--gtest_print_time'],
535 })
532 run_as = spec.get('run_as')
533 if run_as:
536534 action = run_as.get('action', [])
537535 working_directory = run_as.get('working_directory')
538536 if not working_directory:
563561 fp.write(' env.Requires(prerequisite, dependencies)\n')
564562 fp.write('env.Requires(gyp_target, prerequisites)\n')
565563
566 if spec.get('run_as', 0) or int(spec.get('test', 0)):
564 if run_as:
567565 fp.write(_run_as_template_suffix % {
568566 'target_name': target_name,
569567 })
2929 # SHARED_INTERMEDIATE_DIR is the same, except that it is shared among all
3030 # targets that share the same BUILT_PRODUCTS_DIR.
3131 _shared_intermediate_var = 'SHARED_INTERMEDIATE_DIR'
32
33 _library_search_paths_var = 'LIBRARY_SEARCH_PATHS'
3234
3335 generator_default_variables = {
3436 'EXECUTABLE_PREFIX': '',
5759 # The Xcode-specific sections that hold paths.
5860 generator_additional_path_sections = [
5961 'mac_bundle_resources',
62 'mac_framework_headers',
63 'mac_framework_private_headers',
6064 # 'mac_framework_dirs', input already handles _dirs endings.
6165 ]
6266
6569 generator_additional_non_configuration_keys = [
6670 'mac_bundle',
6771 'mac_bundle_resources',
72 'mac_framework_headers',
73 'mac_framework_private_headers',
6874 'xcode_create_dependents_test_runner',
6975 ]
7076
7177 # We want to let any rules apply to files that are resources also.
7278 generator_extra_sources_for_rules = [
7379 'mac_bundle_resources',
80 'mac_framework_headers',
81 'mac_framework_private_headers',
7482 ]
7583
84 # Xcode's standard set of library directories, which don't need to be duplicated
85 # in LIBRARY_SEARCH_PATHS. This list is not exhaustive, but that's okay.
86 xcode_standard_library_dirs = frozenset([
87 '$(SDKROOT)/usr/lib',
88 '$(SDKROOT)/usr/local/lib',
89 ])
7690
7791 def CreateXCConfigurationList(configuration_names):
7892 xccl = gyp.xcodeproj_file.XCConfigurationList({'buildConfigurations': []})
93 if len(configuration_names) == 0:
94 configuration_names = ['Default']
7995 for configuration_name in configuration_names:
8096 xcbc = gyp.xcodeproj_file.XCBuildConfiguration({
8197 'name': configuration_name})
150166 xccl.SetBuildSetting(_shared_intermediate_var,
151167 '$(SYMROOT)/DerivedSources/$(CONFIGURATION)')
152168
153 # Set user-specified project-wide build settings. This is intended to be
154 # used very sparingly. Really, almost everything should go into
155 # target-specific build settings sections. The project-wide settings are
156 # only intended to be used in cases where Xcode attempts to resolve
157 # variable references in a project context as opposed to a target context,
158 # such as when resolving sourceTree references while building up the tree
159 # tree view for UI display.
169 # Set user-specified project-wide build settings and config files. This
170 # is intended to be used very sparingly. Really, almost everything should
171 # go into target-specific build settings sections. The project-wide
172 # settings are only intended to be used in cases where Xcode attempts to
173 # resolve variable references in a project context as opposed to a target
174 # context, such as when resolving sourceTree references while building up
175 # the tree tree view for UI display.
176 # Any values set globally are applied to all configurations, then any
177 # per-configuration values are applied.
160178 for xck, xcv in self.build_file_dict.get('xcode_settings', {}).iteritems():
161179 xccl.SetBuildSetting(xck, xcv)
180 if 'xcode_config_file' in self.build_file_dict:
181 config_ref = self.project.AddOrGetFileInRootGroup(
182 self.build_file_dict['xcode_config_file'])
183 xccl.SetBaseConfiguration(config_ref)
184 build_file_configurations = self.build_file_dict.get('configurations', {})
185 if build_file_configurations:
186 for config_name in configurations:
187 build_file_configuration_named = \
188 build_file_configurations.get(config_name, {})
189 if build_file_configuration_named:
190 xcc = xccl.ConfigurationNamed(config_name)
191 for xck, xcv in build_file_configuration_named.get('xcode_settings',
192 {}).iteritems():
193 xcc.SetBuildSetting(xck, xcv)
194 if 'xcode_config_file' in build_file_configuration_named:
195 config_ref = self.project.AddOrGetFileInRootGroup(
196 build_file_configurations[config_name]['xcode_config_file'])
197 xcc.SetBaseConfiguration(config_ref)
162198
163199 # Sort the targets based on how they appeared in the input.
164200 # TODO(mark): Like a lot of other things here, this assumes internal
204240 if target_name.lower() == 'all':
205241 has_custom_all = True;
206242
207 # If this target has a 'run_as' attribute, or is a test, add its
208 # target to the targets, and (if it's a test) add it the to the
209 # test targets.
210 is_test = int(target.get('test', 0))
211 if target.get('run_as') or is_test:
243 # If this target has a 'run_as' attribute, add its target to the
244 # targets, and add it to the test targets.
245 if target.get('run_as'):
212246 # Make a target to run something. It should have one
213247 # dependency, the parent xcode target.
214248 xccl = CreateXCConfigurationList(configurations)
220254 parent=self.project)
221255 run_target.AddDependency(xcode_target)
222256
223 # The test runner target has a build phase that executes the
224 # test, if this has the 'test' attribute. If the 'run_as' tag
225 # doesn't exist (meaning that this must be a test), then we
226 # define a default test command line.
227 command = target.get('run_as', {
228 'action': ['${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}']
229 })
230
257 command = target['run_as']
231258 script = ''
232259 if command.get('working_directory'):
233260 script = script + 'cd "%s"\n' % \
247274 # little bit of python does the same as the linux flock utility to
248275 # make sure only one runs at a time.
249276 command_prefix = ''
250 if is_test and serialize_all_tests:
277 if serialize_all_tests:
251278 command_prefix = \
252279 """python -c "import fcntl, subprocess, sys
253280 file = open('$TMPDIR/GYP_serialize_test_runs', 'a')
269296
270297 # Add the run target to the project file.
271298 targets.append(run_target)
272 if is_test:
273 run_test_targets.append(run_target)
274 xcode_target.test_runner = run_target
299 run_test_targets.append(run_target)
300 xcode_target.test_runner = run_target
275301
276302
277303 # Make sure that the list of targets being replaced is the same length as
351377 for pbxtd in pbxtds:
352378 pbxcip = pbxtd.GetProperty('targetProxy')
353379 dependency_xct = pbxcip.GetProperty('remoteGlobalIDString')
354 target_dict = xcode_target_to_target_dict[dependency_xct]
355 if target_dict and int(target_dict.get('test', 0)):
356 assert dependency_xct.test_runner
380 if hasattr(dependency_xct, 'test_runner'):
357381 all_run_tests.append(dependency_xct.test_runner)
358382
359383 # Directly depend on all the runners as they depend on the target
490514
491515
492516 def AddSourceToTarget(source, pbxp, xct):
493 # TODO(mark): Perhaps this can be made a little bit fancier.
517 # TODO(mark): Perhaps source_extensions and library_extensions can be made a
518 # little bit fancier.
494519 source_extensions = ['c', 'cc', 'cpp', 'cxx', 'm', 'mm', 's']
520
521 # .o is conceptually more of a "source" than a "library," but Xcode thinks
522 # of "sources" as things to compile and "libraries" (or "frameworks") as
523 # things to link with. Adding an object file to an Xcode target's frameworks
524 # phase works properly.
525 library_extensions = ['a', 'dylib', 'framework', 'o']
526
495527 basename = posixpath.basename(source)
496528 (root, ext) = posixpath.splitext(basename)
497529 if ext != '':
499531
500532 if ext in source_extensions:
501533 xct.SourcesPhase().AddFile(source)
534 elif ext in library_extensions:
535 xct.FrameworksPhase().AddFile(source)
502536 else:
503 # Files that aren't added to a sources build phase can still go into
504 # the project file, just not as part of a build phase.
537 # Files that aren't added to a sources or frameworks build phase can still
538 # go into the project file, just not as part of a build phase.
505539 pbxp.AddOrGetFileInRootGroup(source)
506540
507541
509543 # TODO(mark): Combine with AddSourceToTarget above? Or just inline this call
510544 # where it's used.
511545 xct.ResourcesPhase().AddFile(resource)
546
547
548 def AddHeaderToTarget(header, pbxp, xct, is_public):
549 # TODO(mark): Combine with AddSourceToTarget above? Or just inline this call
550 # where it's used.
551 settings = '{ATTRIBUTES = (%s, ); }' % ('Private', 'Public')[is_public]
552 xct.HeadersPhase().AddFile(header, settings)
512553
513554
514555 _xcode_variable_re = re.compile('(\$\((.*?)\))')
552593 parallel_builds = generator_flags.get('xcode_parallel_builds', True)
553594 serialize_all_tests = \
554595 generator_flags.get('xcode_serialize_all_test_runs', True)
596 project_version = generator_flags.get('xcode_project_version', None)
597 skip_excluded_files = \
598 not generator_flags.get('xcode_list_excluded_files', True)
555599 xcode_projects = {}
556600 for build_file, build_file_dict in data.iteritems():
557601 (build_file_root, build_file_ext) = os.path.splitext(build_file)
567611 if parallel_builds:
568612 pbxp.SetProperty('attributes',
569613 {'BuildIndependentTargetsInParallel': 'YES'})
614 if project_version:
615 xcp.project_file.SetXcodeVersion(project_version)
570616
571617 main_group = pbxp.GetProperty('mainGroup')
572618 build_group = gyp.xcodeproj_file.PBXGroup({'name': 'Build'})
596642 # supplied.
597643 xccl = CreateXCConfigurationList(configuration_names)
598644
599 # Create an XCTarget subclass object for the target. We use the type
600 # with "+bundle" appended if the target has "mac_bundle" set.
645 # Create an XCTarget subclass object for the target. The type with
646 # "+bundle" appended will be used if the target has "mac_bundle" set.
647 # loadable_modules not in a mac_bundle are mapped to
648 # com.googlecode.gyp.xcode.bundle, a pseudo-type that xcode.py interprets
649 # to create a single-file mh_bundle.
601650 _types = {
602651 'executable': 'com.apple.product-type.tool',
603 'loadable_module': 'com.apple.product-type.library.dynamic',
652 'loadable_module': 'com.googlecode.gyp.xcode.bundle',
604653 'shared_library': 'com.apple.product-type.library.dynamic',
605654 'static_library': 'com.apple.product-type.library.static',
606655 'executable+bundle': 'com.apple.product-type.application',
640689 pbxp.AppendProperty('targets', xct)
641690 xcode_targets[qualified_target] = xct
642691 xcode_target_to_target_dict[xct] = spec
643
644 # Xcode does not have a distinct type for loadable_modules that are pure
645 # BSD targets (ie-unbundled). It uses the same setup as a shared_library
646 # but the mach-o type is explictly set in the settings. So before we do
647 # anything else, for this one case, we stuff in that one setting. This
648 # would allow the other data in the spec to change it if need be.
649 if type == 'loadable_module' and not is_bundle:
650 xccl.SetBuildSetting('MACH_O_TYPE', 'mh_bundle')
651692
652693 spec_actions = spec.get('actions', [])
653694 spec_rules = spec.get('rules', [])
868909 message = rule.get('message')
869910 if message:
870911 message = gyp.common.EncodePOSIXShellArgument(message)
871 message = '@echo note: ' + ExpandXcodeVariables(message,
872 rule_input_dict)
912 message = ExpandXcodeVariables(message, rule_input_dict)
873913 messages.append(message)
874914
875915 # Turn the list into a string that can be passed to a shell.
946986
947987 # Make sure that output directories exist before executing the rule
948988 # action.
949 # TODO(mark): quote the list of concrete_output_dirs.
950989 if len(concrete_output_dirs) > 0:
951 makefile.write('\tmkdir -p %s\n' % ' '.join(concrete_output_dirs))
990 makefile.write('\t@mkdir -p "%s"\n' %
991 '" "'.join(concrete_output_dirs))
952992
953993 # The rule message and action have already had the necessary variable
954994 # substitutions performed.
955995 if message:
956 makefile.write('\t%s\n' % message)
996 # Mark it with note: so Xcode picks it up in build output.
997 makefile.write('\t@echo note: %s\n' % message)
957998 makefile.write('\t%s\n' % action)
958999
9591000 makefile.close()
10051046
10061047 # Extra rule inputs also go into the project file. Concrete outputs were
10071048 # already added when they were computed.
1008 for group in ['inputs', 'inputs_excluded']:
1049 groups = ['inputs', 'inputs_excluded']
1050 if skip_excluded_files:
1051 groups = [x for x in groups if not x.endswith('_excluded')]
1052 for group in groups:
10091053 for item in rule.get(group, []):
10101054 pbxp.AddOrGetFileInRootGroup(item)
10111055
10191063 else:
10201064 pbxp.AddOrGetFileInRootGroup(source)
10211065
1022 # Add "mac_bundle_resources" if it's a bundle of any type.
1066 # Add "mac_bundle_resources", "mac_framework_headers", and
1067 # "mac_framework_private_headers" if it's a bundle of any type.
10231068 if is_bundle:
10241069 for resource in tgt_mac_bundle_resources:
10251070 (resource_root, resource_extension) = posixpath.splitext(resource)
10271072 AddResourceToTarget(resource, pbxp, xct)
10281073 else:
10291074 pbxp.AddOrGetFileInRootGroup(resource)
1075
1076 for header in spec.get('mac_framework_headers', []):
1077 AddHeaderToTarget(header, pbxp, xct, True)
1078
1079 for header in spec.get('mac_framework_private_headers', []):
1080 AddHeaderToTarget(header, pbxp, xct, False)
10301081
10311082 # Add "copies".
10321083 for copy_group in spec.get('copies', []):
10481099 pbxcp.AddFile(file)
10491100
10501101 # Excluded files can also go into the project file.
1051 for key in ['sources', 'mac_bundle_resources']:
1052 excluded_key = key + '_excluded'
1053 for item in spec.get(excluded_key, []):
1054 pbxp.AddOrGetFileInRootGroup(item)
1102 if not skip_excluded_files:
1103 for key in ['sources', 'mac_bundle_resources', 'mac_framework_headers',
1104 'mac_framework_private_headers']:
1105 excluded_key = key + '_excluded'
1106 for item in spec.get(excluded_key, []):
1107 pbxp.AddOrGetFileInRootGroup(item)
10551108
10561109 # So can "inputs" and "outputs" sections of "actions" groups.
1110 groups = ['inputs', 'inputs_excluded', 'outputs', 'outputs_excluded']
1111 if skip_excluded_files:
1112 groups = [x for x in groups if not x.endswith('_excluded')]
10571113 for action in spec.get('actions', []):
1058 groups = ['inputs', 'inputs_excluded', 'outputs', 'outputs_excluded']
10591114 for group in groups:
10601115 for item in action.get(group, []):
10611116 # Exclude anything in BUILT_PRODUCTS_DIR. They're products, not
10661121 for postbuild in spec.get('postbuilds', []):
10671122 action_string_sh = gyp.common.EncodePOSIXShellList(postbuild['action'])
10681123 script = 'exec ' + action_string_sh + '\nexit 1\n'
1124
1125 # Make the postbuild step depend on the output of ld or ar from this
1126 # target. Apparently putting the script step after the link step isn't
1127 # sufficient to ensure proper ordering in all cases. With an input
1128 # declared but no outputs, the script step should run every time, as
1129 # desired.
10691130 ssbp = gyp.xcodeproj_file.PBXShellScriptBuildPhase({
1131 'inputPaths': ['$(BUILT_PRODUCTS_DIR)/$(EXECUTABLE_PATH)'],
10701132 'name': 'Postbuild "' + postbuild['postbuild_name'] + '"',
10711133 'shellScript': script,
10721134 'showEnvVarsInLog': 0,
10971159 xct.FrameworksPhase().AddFile(library)
10981160 # Add the library's directory to LIBRARY_SEARCH_PATHS if necessary.
10991161 # I wish Xcode handled this automatically.
1100 # TODO(mark): this logic isn't right. There are certain directories
1101 # that are always searched, we should check to see if the library is
1102 # in one of those directories, and if not, we should do the
1103 # AppendBuildSetting thing.
1104 if not posixpath.isabs(library) and not library.startswith('$'):
1105 # TODO(mark): Need to check to see if library_dir is already in
1106 # LIBRARY_SEARCH_PATHS.
1107 library_dir = posixpath.dirname(library)
1108 xct.AppendBuildSetting('LIBRARY_SEARCH_PATHS', library_dir)
1162 library_dir = posixpath.dirname(library)
1163 if library_dir not in xcode_standard_library_dirs and (
1164 not xct.HasBuildSetting(_library_search_paths_var) or
1165 library_dir not in xct.GetBuildSetting(_library_search_paths_var)):
1166 xct.AppendBuildSetting(_library_search_paths_var, library_dir)
11091167
11101168 for configuration_name in configuration_names:
11111169 configuration = spec['configurations'][configuration_name]
11211179 if 'xcode_settings' in configuration:
11221180 for xck, xcv in configuration['xcode_settings'].iteritems():
11231181 xcbc.SetBuildSetting(xck, xcv)
1182 if 'xcode_config_file' in configuration:
1183 config_ref = pbxp.AddOrGetFileInRootGroup(
1184 configuration['xcode_config_file'])
1185 xcbc.SetBaseConfiguration(config_ref)
11241186
11251187 build_files = []
11261188 for build_file, build_file_dict in data.iteritems():
00 #!/usr/bin/python
11
2 # Copyright (c) 2009 Google Inc. All rights reserved.
2 # Copyright (c) 2011 The Chromium Authors. All rights reserved.
33 # Use of this source code is governed by a BSD-style license that can be
44 # found in the LICENSE file.
55
8282 'sources',
8383 'suppress_wildcard',
8484 'target_name',
85 'test',
8685 'toolset',
8786 'toolsets',
8887 'type',
9392 'variables',
9493 ]
9594 non_configuration_keys = []
95
96 # Keys that do not belong inside a configuration dictionary.
97 invalid_configuration_keys = [
98 'actions',
99 'all_dependent_settings',
100 'configurations',
101 'dependencies',
102 'direct_dependent_settings',
103 'libraries',
104 'link_settings',
105 'sources',
106 'target_name',
107 'type',
108 ]
96109
97110 # Controls how the generator want the build file paths.
98111 absolute_build_file_paths = False
759772 # It's possible that condition[0] won't work in which case this
760773 # attempt will raise its own IndexError. That's probably fine.
761774 raise IndexError, conditions_key + ' ' + condition[0] + \
762 ' must be length 2 or 3, not ' + len(condition)
775 ' must be length 2 or 3, not ' + str(len(condition))
763776
764777 [cond_expr, true_dict] = condition[0:2]
765778 false_dict = None
17831796 for key in delete_keys:
17841797 del target_dict[key]
17851798
1799 # Check the configurations to see if they contain invalid keys.
1800 for configuration in target_dict['configurations'].keys():
1801 configuration_dict = target_dict['configurations'][configuration]
1802 for key in configuration_dict.keys():
1803 if key in invalid_configuration_keys:
1804 raise KeyError, ('%s not allowed in the %s configuration, found in '
1805 'target %s' % (key, configuration, target))
1806
1807
17861808
17871809 def ProcessListFiltersInDict(name, the_dict):
17881810 """Process regular expression and exclusion-based filters on lists.
20782100 TurnIntIntoStrInList(item)
20792101
20802102
2103 def VerifyNoCollidingTargets(targets):
2104 """Verify that no two targets in the same directory share the same name.
2105
2106 Arguments:
2107 targets: A list of targets in the form 'path/to/file.gyp:target_name'.
2108 """
2109 # Keep a dict going from 'subdirectory:target_name' to 'foo.gyp'.
2110 used = {}
2111 for target in targets:
2112 # Separate out 'path/to/file.gyp, 'target_name' from
2113 # 'path/to/file.gyp:target_name'.
2114 path, name = target.rsplit(':', 1)
2115 # Separate out 'path/to', 'file.gyp' from 'path/to/file.gyp'.
2116 subdir, gyp = os.path.split(path)
2117 # Use '.' for the current directory '', so that the error messages make
2118 # more sense.
2119 if not subdir:
2120 subdir = '.'
2121 # Prepare a key like 'path/to:target_name'.
2122 key = subdir + ':' + name
2123 if key in used:
2124 # Complain if this target is already used.
2125 raise Exception('Duplicate target name "%s" in directory "%s" used both '
2126 'in "%s" and "%s".' % (name, subdir, gyp, used[key]))
2127 used[key] = gyp
2128
2129
20812130 def Load(build_files, variables, includes, depth, generator_input_info, check,
20822131 circular_check):
20832132 # Set up path_sections and non_configuration_keys with the default data plus
21422191
21432192 [dependency_nodes, flat_list] = BuildDependencyList(targets)
21442193
2194 # Check that no two targets in the same directory have the same name.
2195 VerifyNoCollidingTargets(flat_list)
2196
2197
21452198 # Handle dependent settings of various types.
21462199 for settings_type in ['all_dependent_settings',
21472200 'direct_dependent_settings',
0 #!/usr/bin/python
1
2 # Copyright (c) 2011 Google Inc. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 import os
7 import tempfile
8 import shutil
9 import subprocess
10
11 def TestCommands(commands, files={}, env={}):
12 """Run commands in a temporary directory, returning true if they all succeed.
13 Return false on failures or if any commands produce output.
14
15 Arguments:
16 commands: an array of shell-interpretable commands, e.g. ['ls -l', 'pwd']
17 each will be expanded with Python %-expansion using env first.
18 files: a dictionary mapping filename to contents;
19 files will be created in the temporary directory before running
20 the command.
21 env: a dictionary of strings to expand commands with.
22 """
23 tempdir = tempfile.mkdtemp()
24 try:
25 for name, contents in files.items():
26 f = open(os.path.join(tempdir, name), 'wb')
27 f.write(contents)
28 f.close()
29 for command in commands:
30 proc = subprocess.Popen(command % env, shell=True,
31 stdout=subprocess.PIPE,
32 stderr=subprocess.STDOUT,
33 cwd=tempdir)
34 output = proc.communicate()[0]
35 if proc.returncode != 0 or output:
36 return False
37 return True
38 finally:
39 shutil.rmtree(tempdir)
40 return False
41
42
43 def TestArSupportsT(ar_command='ar', cc_command='cc'):
44 """Test whether 'ar' supports the 'T' flag."""
45 return TestCommands(['%(cc)s -c test.c',
46 '%(ar)s crsT test.a test.o',
47 '%(cc)s test.a'],
48 files={'test.c': 'int main(){}'},
49 env={'ar': ar_command, 'cc': cc_command})
50
51
52 def TestLinkerSupportsThreads(cc_command='cc'):
53 """Test whether the linker supports the --threads flag."""
54 return TestCommands(['%(cc)s -Wl,--threads test.c'],
55 files={'test.c': 'int main(){}'},
56 env={'cc': cc_command})
57
58
59 def TestLinkerSupportsICF(cc_command='cc'):
60 """Test whether the linker supports identical code folding."""
61 return TestCommands(['%(cc)s -Wl,--icf=safe test.c'],
62 files={'test.c': 'int main(){}'},
63 env={'cc': cc_command})
64
65
66 if __name__ == '__main__':
67 # Run the various test functions and print the results.
68 def RunTest(description, function, **kwargs):
69 print "Testing " + description + ':',
70 if function(**kwargs):
71 print 'ok'
72 else:
73 print 'fail'
74 RunTest("ar 'T' flag", TestArSupportsT)
75 RunTest("ar 'T' flag with ccache", TestArSupportsT, cc_command='ccache cc')
76 RunTest("ld --threads", TestLinkerSupportsThreads)
656656 else:
657657 value_to_print = value
658658
659 # PBXBuildFile's settings property is represented in the output as a dict,
660 # but a hack here has it represented as a string. Arrange to strip off the
661 # quotes so that it shows up in the output as expected.
662 if key == 'settings' and isinstance(self, PBXBuildFile):
663 strip_value_quotes = True
664 else:
665 strip_value_quotes = False
666
659667 # In another one-off, let's set flatten_list on buildSettings properties
660668 # of XCBuildConfiguration objects, because that's how Xcode treats them.
661669 if key == 'buildSettings' and isinstance(self, XCBuildConfiguration):
664672 flatten_list = False
665673
666674 try:
667 printable += self._XCPrintableValue(tabs, key, flatten_list) + ' = ' + \
668 self._XCPrintableValue(tabs, value_to_print, flatten_list) + \
669 ';' + after_kv
675 printable_key = self._XCPrintableValue(tabs, key, flatten_list)
676 printable_value = self._XCPrintableValue(tabs, value_to_print,
677 flatten_list)
678 if strip_value_quotes and len(printable_value) > 1 and \
679 printable_value[0] == '"' and printable_value[-1] == '"':
680 printable_value = printable_value[1:-1]
681 printable += printable_key + ' = ' + printable_value + ';' + after_kv
670682 except TypeError, e:
671683 gyp.common.ExceptionAppend(e,
672684 'while printing key "%s"' % key)
14501462 'm': 'sourcecode.c.objc',
14511463 'mm': 'sourcecode.cpp.objcpp',
14521464 'nib': 'wrapper.nib',
1465 'o': 'compiled.mach-o.objfile',
14531466 'pdf': 'image.pdf',
14541467 'pl': 'text.script.perl',
14551468 'plist': 'text.plist.xml',
15231536 if key in self._properties['buildSettings']:
15241537 del self._properties['buildSettings'][key]
15251538
1539 def SetBaseConfiguration(self, value):
1540 self._properties['baseConfigurationReference'] = value
15261541
15271542 class XCConfigurationList(XCObject):
15281543 # _configs is the default list of configurations.
16311646 for configuration in self._properties['buildConfigurations']:
16321647 configuration.DelBuildSetting(key)
16331648
1649 def SetBaseConfiguration(self, value):
1650 """Sets the build configuration in all child XCBuildConfiguration objects.
1651 """
1652
1653 for configuration in self._properties['buildConfigurations']:
1654 configuration.SetBaseConfiguration(value)
1655
16341656
16351657 class PBXBuildFile(XCObject):
16361658 _schema = XCObject._schema.copy()
16371659 _schema.update({
1638 'fileRef': [0, XCFileLikeElement, 0, 1],
1660 'fileRef': [0, XCFileLikeElement, 0, 1],
1661 'settings': [0, str, 0, 0], # hack, it's a dict
16391662 })
16401663
16411664 # Weird output rules for PBXBuildFile.
17801803 self.AppendProperty('files', pbxbuildfile)
17811804 self._AddBuildFileToDicts(pbxbuildfile, path)
17821805
1783 def AddFile(self, path):
1806 def AddFile(self, path, settings=None):
17841807 (file_group, hierarchical) = self.FileGroup(path)
17851808 file_ref = file_group.AddOrGetFileByPath(path, hierarchical)
17861809
17931816 self._AddBuildFileToDicts(pbxbuildfile, path)
17941817 else:
17951818 # Add a new PBXBuildFile to get file_ref into the phase.
1796 pbxbuildfile = PBXBuildFile({'fileRef': file_ref})
1819 if settings is None:
1820 pbxbuildfile = PBXBuildFile({'fileRef': file_ref})
1821 else:
1822 pbxbuildfile = PBXBuildFile({'fileRef': file_ref, 'settings': settings})
17971823 self.AppendBuildFile(pbxbuildfile, path)
17981824
17991825
18341860 return 'Frameworks'
18351861
18361862 def FileGroup(self, path):
1837 return (self.PBXProjectAncestor().FrameworksGroup(), False)
1863 (root, ext) = posixpath.splitext(path)
1864 if ext != '':
1865 ext = ext[1:].lower()
1866 if ext == 'o':
1867 # .o files are added to Xcode Frameworks phases, but conceptually aren't
1868 # frameworks, they're more like sources or intermediates. Redirect them
1869 # to show up in one of those other groups.
1870 return self.PBXProjectAncestor().RootGroupForPath(path)
1871 else:
1872 return (self.PBXProjectAncestor().FrameworksGroup(), False)
18381873
18391874
18401875 class PBXShellScriptBuildPhase(XCBuildPhase):
21602195 # filetype : used for explicitFileType in the project file
21612196 # prefix : the prefix for the file name
21622197 # suffix : the suffix for the filen ame
2163 # set_xc_exe_prefix : bool to say if EXECUTABLE_PREFIX should be set to the
2164 # prefix value.
21652198 _product_filetypes = {
21662199 'com.apple.product-type.application': ['wrapper.application',
2167 '', '.app', False],
2200 '', '.app'],
21682201 'com.apple.product-type.bundle': ['wrapper.cfbundle',
2169 '', '.bundle', False],
2202 '', '.bundle'],
21702203 'com.apple.product-type.framework': ['wrapper.framework',
2171 '', '.framework', False],
2204 '', '.framework'],
21722205 'com.apple.product-type.library.dynamic': ['compiled.mach-o.dylib',
2173 'lib', '.dylib', True],
2206 'lib', '.dylib'],
21742207 'com.apple.product-type.library.static': ['archive.ar',
2175 'lib', '.a', False],
2208 'lib', '.a'],
21762209 'com.apple.product-type.tool': ['compiled.mach-o.executable',
2177 '', '', False],
2210 '', ''],
2211 'com.googlecode.gyp.xcode.bundle': ['compiled.mach-o.dylib',
2212 '', '.so'],
21782213 }
21792214
21802215 def __init__(self, properties=None, id=None, parent=None,
21922227 products_group = pbxproject.ProductsGroup()
21932228
21942229 if products_group != None:
2195 (filetype, prefix, suffix, set_xc_exe_prefix) = \
2230 (filetype, prefix, suffix) = \
21962231 self._product_filetypes[self._properties['productType']]
2232 # Xcode does not have a distinct type for loadable modules that are
2233 # pure BSD targets (not in a bundle wrapper). GYP allows such modules
2234 # to be specified by setting a target type to loadable_module without
2235 # having mac_bundle set. These are mapped to the pseudo-product type
2236 # com.googlecode.gyp.xcode.bundle.
2237 #
2238 # By picking up this special type and converting it to a dynamic
2239 # library (com.apple.product-type.library.dynamic) with fix-ups,
2240 # single-file loadable modules can be produced.
2241 #
2242 # MACH_O_TYPE is changed to mh_bundle to produce the proper file type
2243 # (as opposed to mh_dylib). In order for linking to succeed,
2244 # DYLIB_CURRENT_VERSION and DYLIB_COMPATIBILITY_VERSION must be
2245 # cleared. They are meaningless for type mh_bundle.
2246 #
2247 # Finally, the .so extension is forcibly applied over the default
2248 # (.dylib), unless another forced extension is already selected.
2249 # .dylib is plainly wrong, and .bundle is used by loadable_modules in
2250 # bundle wrappers (com.apple.product-type.bundle). .so seems an odd
2251 # choice because it's used as the extension on many other systems that
2252 # don't distinguish between linkable shared libraries and non-linkable
2253 # loadable modules, but there's precedent: Python loadable modules on
2254 # Mac OS X use an .so extension.
2255 if self._properties['productType'] == 'com.googlecode.gyp.xcode.bundle':
2256 self._properties['productType'] = \
2257 'com.apple.product-type.library.dynamic'
2258 self.SetBuildSetting('MACH_O_TYPE', 'mh_bundle')
2259 self.SetBuildSetting('DYLIB_CURRENT_VERSION', '')
2260 self.SetBuildSetting('DYLIB_COMPATIBILITY_VERSION', '')
2261 if force_extension == None:
2262 force_extension = suffix[1:]
21972263
21982264 if force_extension is not None:
21992265 # If it's a wrapper (bundle), set WRAPPER_EXTENSION.
22662332 the_phase = phase
22672333
22682334 return the_phase
2335
2336 def HeadersPhase(self):
2337 headers_phase = self.GetBuildPhaseByType(PBXHeadersBuildPhase)
2338 if headers_phase == None:
2339 headers_phase = PBXHeadersBuildPhase()
2340
2341 # The headers phase should come before the resources, sources, and
2342 # frameworks phases, if any.
2343 insert_at = len(self._properties['buildPhases'])
2344 for index in xrange(0, len(self._properties['buildPhases'])):
2345 phase = self._properties['buildPhases'][index]
2346 if isinstance(phase, PBXResourcesBuildPhase) or \
2347 isinstance(phase, PBXSourcesBuildPhase) or \
2348 isinstance(phase, PBXFrameworksBuildPhase):
2349 insert_at = index
2350 break
2351
2352 self._properties['buildPhases'].insert(insert_at, headers_phase)
2353 headers_phase.parent = self
2354
2355 return headers_phase
22692356
22702357 def ResourcesPhase(self):
22712358 resources_phase = self.GetBuildPhaseByType(PBXResourcesBuildPhase)
26782765 'rootObject': [0, PBXProject, 1, 1],
26792766 })
26802767
2768 def SetXcodeVersion(self, version):
2769 version_to_object_version = {
2770 '2.4': 45,
2771 '3.0': 45,
2772 '3.1': 45,
2773 '3.2': 46,
2774 }
2775 if not version in version_to_object_version:
2776 supported_str = ', '.join(sorted(version_to_object_version.keys()))
2777 raise Exception(
2778 'Unsupported Xcode version %s (supported: %s)' %
2779 ( version, supported_str ) )
2780 compatibility_version = 'Xcode %s' % version
2781 self._properties['rootObject'].SetProperty('compatibilityVersion',
2782 compatibility_version)
2783 self.SetProperty('objectVersion', version_to_object_version[version]);
2784
26812785 def ComputeIDs(self, recursive=True, overwrite=True, hash=None):
26822786 # Although XCProjectFile is implemented here as an XCObject, it's not a
26832787 # proper object in the Xcode sense, and it certainly doesn't have its own
0 #!/usr/bin/python
1 # Copyright (c) 2011 Google Inc. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4
5 """Applies a fix to CR LF TAB handling in xml.dom.
6
7 Fixes this: http://code.google.com/p/chromium/issues/detail?id=76293
8 Working around this: http://bugs.python.org/issue5752
9 TODO(bradnelson): Consider dropping this when we drop XP support.
10 """
11
12
13 import xml.dom.minidom
14
15
16 def _Replacement_write_data(writer, data, is_attrib=False):
17 """Writes datachars to writer."""
18 data = data.replace("&", "&amp;").replace("<", "&lt;")
19 data = data.replace("\"", "&quot;").replace(">", "&gt;")
20 if is_attrib:
21 data = data.replace(
22 "\r", "&#xD;").replace(
23 "\n", "&#xA;").replace(
24 "\t", "&#x9;")
25 writer.write(data)
26
27
28 def _Replacement_writexml(self, writer, indent="", addindent="", newl=""):
29 # indent = current indentation
30 # addindent = indentation to add to higher levels
31 # newl = newline string
32 writer.write(indent+"<" + self.tagName)
33
34 attrs = self._get_attributes()
35 a_names = attrs.keys()
36 a_names.sort()
37
38 for a_name in a_names:
39 writer.write(" %s=\"" % a_name)
40 _Replacement_write_data(writer, attrs[a_name].value, is_attrib=True)
41 writer.write("\"")
42 if self.childNodes:
43 writer.write(">%s" % newl)
44 for node in self.childNodes:
45 node.writexml(writer, indent + addindent, addindent, newl)
46 writer.write("%s</%s>%s" % (indent, self.tagName, newl))
47 else:
48 writer.write("/>%s" % newl)
49
50
51 class XmlFix(object):
52 """Object to manage temporary patching of xml.dom.minidom."""
53
54 def __init__(self):
55 # Preserve current xml.dom.minidom functions.
56 self.write_data = xml.dom.minidom._write_data
57 self.writexml = xml.dom.minidom.Element.writexml
58 # Inject replacement versions of a function and a method.
59 xml.dom.minidom._write_data = _Replacement_write_data
60 xml.dom.minidom.Element.writexml = _Replacement_writexml
61
62 def Cleanup(self):
63 if self.write_data:
64 xml.dom.minidom._write_data = self.write_data
65 xml.dom.minidom.Element.writexml = self.writexml
66 self.write_data = None
67
68 def __del__(self):
69 self.Cleanup()
1111 import os
1212 import TestGyp
1313
14 test = TestGyp.TestGyp()
14 test = TestGyp.TestGyp(workdir='workarea_all')
1515
1616 test.run_gyp('actions.gyp', chdir='src')
1717
99
1010 import TestGyp
1111
12 test = TestGyp.TestGyp()
12 test = TestGyp.TestGyp(workdir='workarea_default')
1313
1414 test.run_gyp('actions.gyp', chdir='src')
1515
0 #!/usr/bin/env python
0 #!/usr/bin/env python
11
22 # Copyright (c) 2009 Google Inc. All rights reserved.
33 # Use of this source code is governed by a BSD-style license that can be
44 # found in the LICENSE file.
5
6 """
7 Verifies behavior for different action configuration errors:
8 exit status of 1, and the expected error message must be in stderr.
9 """
10
11 import TestGyp
12
13 test = TestGyp.TestGyp()
14
15
16 test.run_gyp('action_missing_name.gyp', chdir='src', status=1, stderr=None)
17 expect = [
18 "Anonymous action in target broken_actions2. An action must have an 'action_name' field.",
19 ]
20 test.must_contain_all_lines(test.stderr(), expect)
21
22
23 test.pass_test()
5
6 """
7 Verifies behavior for different action configuration errors:
8 exit status of 1, and the expected error message must be in stderr.
9 """
10
11 import TestGyp
12
13 test = TestGyp.TestGyp(workdir='workarea_errors')
14
15
16 test.run_gyp('action_missing_name.gyp', chdir='src', status=1, stderr=None)
17 expect = [
18 "Anonymous action in target broken_actions2. An action must have an 'action_name' field.",
19 ]
20 test.must_contain_all_lines(test.stderr(), expect)
21
22
23 test.pass_test()
0 #!/usr/bin/env python
1
2 # Copyright (c) 2011 Google Inc. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 """
7 Verifies two actions can be attached to the same input files.
8 """
9
10 import TestGyp
11
12 test = TestGyp.TestGyp()
13
14 test.run_gyp('actions.gyp', chdir='src')
15
16 test.relocate('src', 'relocate/src')
17
18 # Test that two actions can be attached to the same inputs.
19 test.build('actions.gyp', test.ALL, chdir='relocate/src')
20 test.must_contain('relocate/src/output1.txt', 'hello there')
21 test.must_contain('relocate/src/output2.txt', 'hello there')
22 test.must_contain('relocate/src/output3.txt', 'hello there')
23 test.must_contain('relocate/src/output4.txt', 'hello there')
24
25 # Test that process_outputs_as_sources works in conjuction with merged
26 # actions.
27 test.run_built_executable(
28 'multiple_action_source_filter',
29 chdir='relocate/src',
30 stdout=(
31 '{\n'
32 'bar\n'
33 'car\n'
34 'dar\n'
35 'ear\n'
36 '}\n'
37 ),
38 )
39
40
41 test.pass_test()
0 # Copyright (c) 2011 Google Inc. All rights reserved.
1 # Use of this source code is governed by a BSD-style license that can be
2 # found in the LICENSE file.
3
4 {
5 'variables': {
6 # Have a long string so that actions will exceed xp 512 character
7 # command limit on xp.
8 'long_string':
9 'abcdefghijklmnopqrstuvwxyz0123456789'
10 'abcdefghijklmnopqrstuvwxyz0123456789'
11 'abcdefghijklmnopqrstuvwxyz0123456789'
12 'abcdefghijklmnopqrstuvwxyz0123456789'
13 'abcdefghijklmnopqrstuvwxyz0123456789'
14 'abcdefghijklmnopqrstuvwxyz0123456789'
15 'abcdefghijklmnopqrstuvwxyz0123456789'
16 'abcdefghijklmnopqrstuvwxyz0123456789'
17 'abcdefghijklmnopqrstuvwxyz0123456789'
18 'abcdefghijklmnopqrstuvwxyz0123456789'
19 'abcdefghijklmnopqrstuvwxyz0123456789'
20 },
21 'targets': [
22 {
23 'target_name': 'multiple_action_target',
24 'type': 'none',
25 'actions': [
26 {
27 'action_name': 'action1',
28 'inputs': [
29 'copy.py',
30 'input.txt',
31 ],
32 'outputs': [
33 'output1.txt',
34 ],
35 'action': [
36 'python', '<@(_inputs)', '<(_outputs)', '<(long_string)',
37 ],
38 # Allows the test to run without hermetic cygwin on windows.
39 'msvs_cygwin_shell': 0,
40 },
41 {
42 'action_name': 'action2',
43 'inputs': [
44 'copy.py',
45 'input.txt',
46 ],
47 'outputs': [
48 'output2.txt',
49 ],
50 'action': [
51 'python', '<@(_inputs)', '<(_outputs)', '<(long_string)',
52 ],
53 # Allows the test to run without hermetic cygwin on windows.
54 'msvs_cygwin_shell': 0,
55 },
56 {
57 'action_name': 'action3',
58 'inputs': [
59 'copy.py',
60 'input.txt',
61 ],
62 'outputs': [
63 'output3.txt',
64 ],
65 'action': [
66 'python', '<@(_inputs)', '<(_outputs)', '<(long_string)',
67 ],
68 # Allows the test to run without hermetic cygwin on windows.
69 'msvs_cygwin_shell': 0,
70 },
71 {
72 'action_name': 'action4',
73 'inputs': [
74 'copy.py',
75 'input.txt',
76 ],
77 'outputs': [
78 'output4.txt',
79 ],
80 'action': [
81 'python', '<@(_inputs)', '<(_outputs)', '<(long_string)',
82 ],
83 # Allows the test to run without hermetic cygwin on windows.
84 'msvs_cygwin_shell': 0,
85 },
86 ],
87 },
88 {
89 'target_name': 'multiple_action_source_filter',
90 'type': 'executable',
91 'sources': [
92 'main.c',
93 # TODO(bradnelson): add foo.c here once this issue is fixed:
94 # http://code.google.com/p/gyp/issues/detail?id=175
95 ],
96 'actions': [
97 {
98 'action_name': 'action1',
99 'inputs': [
100 'foo.c',
101 'filter.py',
102 ],
103 'outputs': [
104 'output1.c',
105 ],
106 'process_outputs_as_sources': 1,
107 'action': [
108 'python', 'filter.py', 'foo', 'bar', 'foo.c', '<(_outputs)',
109 ],
110 # Allows the test to run without hermetic cygwin on windows.
111 'msvs_cygwin_shell': 0,
112 },
113 {
114 'action_name': 'action2',
115 'inputs': [
116 'foo.c',
117 'filter.py',
118 ],
119 'outputs': [
120 'output2.c',
121 ],
122 'process_outputs_as_sources': 1,
123 'action': [
124 'python', 'filter.py', 'foo', 'car', 'foo.c', '<(_outputs)',
125 ],
126 # Allows the test to run without hermetic cygwin on windows.
127 'msvs_cygwin_shell': 0,
128 },
129 {
130 'action_name': 'action3',
131 'inputs': [
132 'foo.c',
133 'filter.py',
134 ],
135 'outputs': [
136 'output3.c',
137 ],
138 'process_outputs_as_sources': 1,
139 'action': [
140 'python', 'filter.py', 'foo', 'dar', 'foo.c', '<(_outputs)',
141 ],
142 # Allows the test to run without hermetic cygwin on windows.
143 'msvs_cygwin_shell': 0,
144 },
145 {
146 'action_name': 'action4',
147 'inputs': [
148 'foo.c',
149 'filter.py',
150 ],
151 'outputs': [
152 'output4.c',
153 ],
154 'process_outputs_as_sources': 1,
155 'action': [
156 'python', 'filter.py', 'foo', 'ear', 'foo.c', '<(_outputs)',
157 ],
158 # Allows the test to run without hermetic cygwin on windows.
159 'msvs_cygwin_shell': 0,
160 },
161 ],
162 },
163 ],
164 }
0 #!/usr/bin/python
1 # Copyright (c) 2011 Google Inc. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4
5 import shutil
6 import sys
7
8 shutil.copyfile(sys.argv[1], sys.argv[2])
0 #!/usr/bin/python
1 # Copyright (c) 2011 Google Inc. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4
5
6 import sys
7
8 data = open(sys.argv[3], 'r').read()
9 fh = open(sys.argv[4], 'w')
10 fh.write(data.replace(sys.argv[1], sys.argv[2]))
11 fh.close()
0 /*
1 * Copyright (c) 2011 Google Inc. All rights reserved.
2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file.
4 */
5
6 #include <stdio.h>
7
8 void foo(void) {
9 printf("foo\n");
10 }
0 /*
1 * Copyright (c) 2011 Google Inc. All rights reserved.
2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file.
4 */
5
6 #include <stdio.h>
7
8 void bar(void);
9 void car(void);
10 void dar(void);
11 void ear(void);
12
13 int main() {
14 printf("{\n");
15 bar();
16 car();
17 dar();
18 ear();
19 printf("}\n");
20 return 0;
21 }
0 /* Copyright (c) 2010 Google Inc. All rights reserved.
1 * Use of this source code is governed by a BSD-style license that can be
2 * found in the LICENSE file. */
3
4 #include <stdio.h>
5
6 int main(int argc, char *argv[])
7 {
8 #ifdef __OPTIMIZE__
9 printf("Using an optimization flag\n");
10 #else
11 printf("Using no optimization flag\n");
12 #endif
13 return 0;
14 }
0 # Copyright (c) 2010 Google Inc. All rights reserved.
1 # Use of this source code is governed by a BSD-style license that can be
2 # found in the LICENSE file.
3
4 {
5 'targets': [
6 {
7 'target_name': 'cflags',
8 'type': 'executable',
9 'opt': '-Os',
10 'sources': [
11 'cflags.c',
12 ],
13 },
14 ],
15 }
0 #!/usr/bin/env python
1
2 # Copyright (c) 2010 Google Inc. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 """
7 Verifies build of an executable with C++ define specified by a gyp define, and
8 the use of the environment during regeneration when the gyp file changes.
9 """
10
11 import os
12 import TestGyp
13
14 env_stack = []
15
16
17 def PushEnv():
18 env_copy = os.environ.copy()
19 env_stack.append(env_copy)
20
21 def PopEnv():
22 os.eniron=env_stack.pop()
23
24 # Regenerating build files when a gyp file changes is currently only supported
25 # by the make generator.
26 test = TestGyp.TestGyp(formats=['make'])
27
28 try:
29 PushEnv()
30 os.environ['CFLAGS'] = '-O0'
31 test.run_gyp('cflags.gyp')
32 finally:
33 # We clear the environ after calling gyp. When the auto-regeneration happens,
34 # the same define should be reused anyway. Reset to empty string first in
35 # case the platform doesn't support unsetenv.
36 PopEnv()
37
38 test.build('cflags.gyp')
39
40 expect = """\
41 Using no optimization flag
42 """
43 test.run_built_executable('cflags', stdout=expect)
44
45 test.sleep()
46
47 try:
48 PushEnv()
49 os.environ['CFLAGS'] = '-O2'
50 test.run_gyp('cflags.gyp')
51 finally:
52 # We clear the environ after calling gyp. When the auto-regeneration happens,
53 # the same define should be reused anyway. Reset to empty string first in
54 # case the platform doesn't support unsetenv.
55 PopEnv()
56
57 test.build('cflags.gyp')
58
59 expect = """\
60 Using an optimization flag
61 """
62 test.run_built_executable('cflags', stdout=expect)
63
64 test.pass_test()
0 # Copyright (c) 2010 Google Inc. All rights reserved.
1 # Use of this source code is governed by a BSD-style license that can be
2 # found in the LICENSE file.
3
4 {
5 'targets': [
6 {
7 'target_name': 'configurations',
8 'type': 'none',
9 'configurations': {
10 'Debug': {
11 'actions': [
12 ],
13 },
14 }
15 },
16 ],
17 }
0 # Copyright (c) 2010 Google Inc. All rights reserved.
1 # Use of this source code is governed by a BSD-style license that can be
2 # found in the LICENSE file.
3
4 {
5 'targets': [
6 {
7 'target_name': 'configurations',
8 'type': 'none',
9 'configurations': {
10 'Debug': {
11 'all_dependent_settings': [
12 ],
13 },
14 }
15 },
16 ],
17 }
0 # Copyright (c) 2010 Google Inc. All rights reserved.
1 # Use of this source code is governed by a BSD-style license that can be
2 # found in the LICENSE file.
3
4 {
5 'targets': [
6 {
7 'target_name': 'configurations',
8 'type': 'none',
9 'configurations': {
10 'Debug': {
11 'configurations': [
12 ],
13 },
14 }
15 },
16 ],
17 }
0 # Copyright (c) 2010 Google Inc. All rights reserved.
1 # Use of this source code is governed by a BSD-style license that can be
2 # found in the LICENSE file.
3
4 {
5 'targets': [
6 {
7 'target_name': 'configurations',
8 'type': 'none',
9 'configurations': {
10 'Debug': {
11 'dependencies': [
12 ],
13 },
14 }
15 },
16 ],
17 }
0 # Copyright (c) 2010 Google Inc. All rights reserved.
1 # Use of this source code is governed by a BSD-style license that can be
2 # found in the LICENSE file.
3
4 {
5 'targets': [
6 {
7 'target_name': 'configurations',
8 'type': 'none',
9 'configurations': {
10 'Debug': {
11 'direct_dependent_settings': [
12 ],
13 },
14 }
15 },
16 ],
17 }
0 #!/usr/bin/env python
1
2 # Copyright (c) 2010 Google Inc. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 """
7 Verifies build of an executable in three different configurations.
8 """
9
10 import TestGyp
11
12 # Keys that do not belong inside a configuration dictionary.
13 invalid_configuration_keys = [
14 'actions',
15 'all_dependent_settings',
16 'configurations',
17 'dependencies',
18 'direct_dependent_settings',
19 'libraries',
20 'link_settings',
21 'sources',
22 'target_name',
23 'type',
24 ]
25
26 test = TestGyp.TestGyp()
27
28 if test.format == 'scons':
29 test.skip_test('TODO: http://code.google.com/p/gyp/issues/detail?id=176\n')
30
31 for test_key in invalid_configuration_keys:
32 test.run_gyp('%s.gyp' % test_key, status=1, stderr=None)
33 expect = ['%s not allowed in the Debug configuration, found in target '
34 '%s.gyp:configurations#target' % (test_key, test_key)]
35 test.must_contain_all_lines(test.stderr(), expect)
36
37 test.pass_test()
0 # Copyright (c) 2010 Google Inc. All rights reserved.
1 # Use of this source code is governed by a BSD-style license that can be
2 # found in the LICENSE file.
3
4 {
5 'targets': [
6 {
7 'target_name': 'configurations',
8 'type': 'none',
9 'configurations': {
10 'Debug': {
11 'libraries': [
12 ],
13 },
14 }
15 },
16 ],
17 }
0 # Copyright (c) 2010 Google Inc. All rights reserved.
1 # Use of this source code is governed by a BSD-style license that can be
2 # found in the LICENSE file.
3
4 {
5 'targets': [
6 {
7 'target_name': 'configurations',
8 'type': 'none',
9 'configurations': {
10 'Debug': {
11 'link_settings': [
12 ],
13 },
14 }
15 },
16 ],
17 }
0 # Copyright (c) 2010 Google Inc. All rights reserved.
1 # Use of this source code is governed by a BSD-style license that can be
2 # found in the LICENSE file.
3
4 {
5 'targets': [
6 {
7 'target_name': 'configurations',
8 'type': 'none',
9 'configurations': {
10 'Debug': {
11 'sources': [
12 ],
13 },
14 }
15 },
16 ],
17 }
0 # Copyright (c) 2010 Google Inc. All rights reserved.
1 # Use of this source code is governed by a BSD-style license that can be
2 # found in the LICENSE file.
3
4 {
5 'targets': [
6 {
7 'target_name': 'configurations',
8 'type': 'none',
9 'configurations': {
10 'Debug': {
11 'target_name': [
12 ],
13 },
14 }
15 },
16 ],
17 }
0 # Copyright (c) 2010 Google Inc. All rights reserved.
1 # Use of this source code is governed by a BSD-style license that can be
2 # found in the LICENSE file.
3
4 {
5 'targets': [
6 {
7 'target_name': 'configurations',
8 'type': 'none',
9 'configurations': {
10 'Debug': {
11 'type': [
12 ],
13 },
14 }
15 },
16 ],
17 }
00 #include <stdio.h>
11
2 extern void func1(void);
3
4 int main(int argc, char *argv[]) {
5 printf("hello from link1\n");
6 func1();
7 return 0;
2 void func1(void) {
3 printf("hello from func1\n");
84 }
00 #include <stdio.h>
11
2 void func1(void) {
3 printf("hello from func1\n");
2 extern void func1(void);
3
4 int main(int argc, char *argv[]) {
5 printf("hello from link1\n");
6 func1();
7 return 0;
48 }
0 /* Copyright (c) 2010 Google Inc. All rights reserved.
1 * Use of this source code is governed by a BSD-style license that can be
2 * found in the LICENSE file. */
3
4 #include <stdio.h>
5
6 int main(int argc, char *argv[])
7 {
8 #ifdef __OPTIMIZE__
9 printf("Using an optimization flag\n");
10 #else
11 printf("Using no optimization flag\n");
12 #endif
13 return 0;
14 }
0 # Copyright (c) 2010 Google Inc. All rights reserved.
1 # Use of this source code is governed by a BSD-style license that can be
2 # found in the LICENSE file.
3
4 {
5 'targets': [
6 {
7 'target_name': 'cxxflags',
8 'type': 'executable',
9 'opt': '-Os',
10 'sources': [
11 'cxxflags.cc',
12 ],
13 },
14 ],
15 }
0 #!/usr/bin/env python
1
2 # Copyright (c) 2010 Google Inc. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 """
7 Verifies build of an executable with C++ define specified by a gyp define, and
8 the use of the environment during regeneration when the gyp file changes.
9 """
10
11 import os
12 import TestGyp
13
14 env_stack = []
15
16
17 def PushEnv():
18 env_copy = os.environ.copy()
19 env_stack.append(env_copy)
20
21 def PopEnv():
22 os.eniron=env_stack.pop()
23
24 # Regenerating build files when a gyp file changes is currently only supported
25 # by the make generator.
26 test = TestGyp.TestGyp(formats=['make'])
27
28 try:
29 PushEnv()
30 os.environ['CXXFLAGS'] = '-O0'
31 test.run_gyp('cxxflags.gyp')
32 finally:
33 # We clear the environ after calling gyp. When the auto-regeneration happens,
34 # the same define should be reused anyway. Reset to empty string first in
35 # case the platform doesn't support unsetenv.
36 PopEnv()
37
38 test.build('cxxflags.gyp')
39
40 expect = """\
41 Using no optimization flag
42 """
43 test.run_built_executable('cxxflags', stdout=expect)
44
45 test.sleep()
46
47 try:
48 PushEnv()
49 os.environ['CXXFLAGS'] = '-O2'
50 test.run_gyp('cxxflags.gyp')
51 finally:
52 # We clear the environ after calling gyp. When the auto-regeneration happens,
53 # the same define should be reused anyway. Reset to empty string first in
54 # case the platform doesn't support unsetenv.
55 PopEnv()
56
57 test.build('cxxflags.gyp')
58
59 expect = """\
60 Using an optimization flag
61 """
62 test.run_built_executable('cxxflags', stdout=expect)
63
64 test.pass_test()
1515
1616 # Tests string literals, percents, and backslash escapes.
1717 try:
18 os.environ['GYP_DEFINES'] = \
19 """test_format='%s\\n' test_args='"Simple test of %s with a literal"'"""
18 os.environ['GYP_DEFINES'] = (
19 r"""test_format='\n%s\n' """
20 r"""test_args='"Simple test of %s with a literal"'""")
2021 test.run_gyp('defines-escaping.gyp')
2122 finally:
2223 del os.environ['GYP_DEFINES']
2324
2425 test.build('defines-escaping.gyp')
2526
26 expect = """\
27 expect = """
2728 Simple test of %s with a literal
2829 """
2930 test.run_built_executable('defines_escaping', stdout=expect)
3233 # Test multiple comma-and-space-separated string literals.
3334 try:
3435 os.environ['GYP_DEFINES'] = \
35 """test_format='%s and %s\\n' test_args='"foo", "bar"'"""
36 r"""test_format='\n%s and %s\n' test_args='"foo", "bar"'"""
3637 test.run_gyp('defines-escaping.gyp')
3738 finally:
3839 del os.environ['GYP_DEFINES']
4142 test.touch('defines-escaping.c')
4243 test.build('defines-escaping.gyp')
4344
44 expect = """\
45 expect = """
4546 foo and bar
4647 """
4748 test.run_built_executable('defines_escaping', stdout=expect)
4950
5051 # Test string literals containing quotes.
5152 try:
52 os.environ['GYP_DEFINES'] = \
53 ("""test_format='%s %s %s %s %s\\n' """ +
54 """test_args='"\\"These,\\"",""" +
55 """ "\\"words,\\"","""
56 """ "\\"are,\\"",""" +
57 """ "\\"in,\\"",""" +
58 """ "\\"quotes.\\""'""")
53 os.environ['GYP_DEFINES'] = (
54 r"""test_format='\n%s %s %s %s %s\n' """
55 r"""test_args='"\"These,\"","""
56 r""" "\"words,\"","""
57 r""" "\"are,\"","""
58 r""" "\"in,\"","""
59 r""" "\"quotes.\""'""")
5960 test.run_gyp('defines-escaping.gyp')
6061 finally:
6162 del os.environ['GYP_DEFINES']
6465 test.touch('defines-escaping.c')
6566 test.build('defines-escaping.gyp')
6667
67 expect = """\
68 expect = """
6869 "These," "words," "are," "in," "quotes."
6970 """
7071 test.run_built_executable('defines_escaping', stdout=expect)
7273
7374 # Test string literals containing single quotes.
7475 try:
75 os.environ['GYP_DEFINES'] = \
76 ("""test_format='%s %s %s %s %s\\n' """ +
77 """test_args="\\"'These,'\\",""" +
78 """ \\"'words,'\\","""
79 """ \\"'are,'\\",""" +
80 """ \\"'in,'\\",""" +
81 """ \\"'quotes.'\\"" """)
76 os.environ['GYP_DEFINES'] = (
77 r"""test_format='\n%s %s %s %s %s\n' """
78 r"""test_args="\"'These,'\","""
79 r""" \"'words,'\","""
80 r""" \"'are,'\","""
81 r""" \"'in,'\","""
82 r""" \"'quotes.'\"" """)
8283 test.run_gyp('defines-escaping.gyp')
8384 finally:
8485 del os.environ['GYP_DEFINES']
8788 test.touch('defines-escaping.c')
8889 test.build('defines-escaping.gyp')
8990
90 expect = """\
91 expect = """
9192 'These,' 'words,' 'are,' 'in,' 'quotes.'
9293 """
9394 test.run_built_executable('defines_escaping', stdout=expect)
9697 # Test string literals containing different numbers of backslashes before quotes
9798 # (to exercise Windows' quoting behaviour).
9899 try:
99 os.environ['GYP_DEFINES'] = \
100 ("""test_format='%s\\n%s\\n%s\\n' """ +
101 """test_args='"\\\\\\"1 visible slash\\\\\\"",""" +
102 """ "\\\\\\\\\\"2 visible slashes\\\\\\\\\\"","""
103 """ "\\\\\\\\\\\\\\"3 visible slashes\\\\\\\\\\\\\\""'""")
100 os.environ['GYP_DEFINES'] = (
101 r"""test_format='\n%s\n%s\n%s\n' """
102 r"""test_args='"\\\"1 visible slash\\\"","""
103 r""" "\\\\\"2 visible slashes\\\\\"","""
104 r""" "\\\\\\\"3 visible slashes\\\\\\\""'""")
104105 test.run_gyp('defines-escaping.gyp')
105106 finally:
106107 del os.environ['GYP_DEFINES']
109110 test.touch('defines-escaping.c')
110111 test.build('defines-escaping.gyp')
111112
112 expect = """\
113 \\"1 visible slash\\"
114 \\\\"2 visible slashes\\\\"
115 \\\\\\"3 visible slashes\\\\\\"
113 expect = r"""
114 \"1 visible slash\"
115 \\"2 visible slashes\\"
116 \\\"3 visible slashes\\\"
116117 """
117118 test.run_built_executable('defines_escaping', stdout=expect)
118119
119120
120121 # Test that various scary sequences are passed unfettered.
121122 try:
122 os.environ['GYP_DEFINES'] = \
123 ("""test_format='%s\\n' """ +
124 """test_args='"%PATH%, $foo, &quot; `foo`;"'""")
123 os.environ['GYP_DEFINES'] = (
124 r"""test_format='\n%s\n' """
125 r"""test_args='"$foo, &quot; `foo`;"'""")
125126 test.run_gyp('defines-escaping.gyp')
126127 finally:
127128 del os.environ['GYP_DEFINES']
130131 test.touch('defines-escaping.c')
131132 test.build('defines-escaping.gyp')
132133
133 expect = """\
134 %PATH%, $foo, &quot; `foo`;
134 expect = """
135 $foo, &quot; `foo`;
135136 """
136137 test.run_built_executable('defines_escaping', stdout=expect)
138
139
140 # VisualStudio 2010 can't handle passing %PATH%
141 if not (test.format == 'msvs' and test.uses_msbuild):
142 try:
143 os.environ['GYP_DEFINES'] = (
144 """test_format='%s' """
145 """test_args='"%PATH%"'""")
146 test.run_gyp('defines-escaping.gyp')
147 finally:
148 del os.environ['GYP_DEFINES']
149
150 test.sleep()
151 test.touch('defines-escaping.c')
152 test.build('defines-escaping.gyp')
153
154 expect = "%PATH%"
155 test.run_built_executable('defines_escaping', stdout=expect)
137156
138157
139158 # Test commas and semi-colons preceded by backslashes (to exercise Windows'
140159 # quoting behaviour).
141160 try:
142 os.environ['GYP_DEFINES'] = \
143 ("""test_format='%s\\n%s\\n' """ +
144 """test_args='"\\\\, \\\\\\\\;",""" +
161 os.environ['GYP_DEFINES'] = (
162 r"""test_format='\n%s\n%s\n' """
163 r"""test_args='"\\, \\\\;","""
145164 # Same thing again, but enclosed in visible quotes.
146 """ "\\"\\\\, \\\\\\\\;\\""'""")
165 r""" "\"\\, \\\\;\""'""")
147166 test.run_gyp('defines-escaping.gyp')
148167 finally:
149168 del os.environ['GYP_DEFINES']
152171 test.touch('defines-escaping.c')
153172 test.build('defines-escaping.gyp')
154173
155 expect = """\
156 \\, \\\\;
157 "\\, \\\\;"
174 expect = r"""
175 \, \\;
176 "\, \\;"
158177 """
159178 test.run_built_executable('defines_escaping', stdout=expect)
160179
0 # Copyright (c) 2010 Google Inc. All rights reserved.
1 # Use of this source code is governed by a BSD-style license that can be
2 # found in the LICENSE file.
3
4 {
5 'targets': [
6 {
7 'target_name': 'hello',
8 'type': 'executable',
9 'sources': [
10 'hello.c',
11 'bogus.c',
12 'also/not/real.c',
13 'also/not/real2.c',
14 ],
15 'sources!': [
16 'bogus.c',
17 'also/not/real.c',
18 'also/not/real2.c',
19 ],
20 },
21 ],
22 }
0 #!/usr/bin/env python
1
2 # Copyright (c) 2010 Google Inc. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 """
7 Verifies that exclusions (e.g. sources!) are respected. Excluded sources
8 that do not exist should not prevent the build from succeeding.
9 """
10
11 import TestGyp
12
13 test = TestGyp.TestGyp()
14
15 test.run_gyp('exclusion.gyp')
16 test.build('exclusion.gyp')
17
18 # executables
19 test.built_file_must_exist('hello' + test._exe, test.EXECUTABLE, bare=True)
20
21 test.pass_test()
0 /* Copyright (c) 2010 Google Inc. All rights reserved.
1 * Use of this source code is governed by a BSD-style license that can be
2 * found in the LICENSE file. */
3
4 #include <stdio.h>
5
6 int func1(void) {
7 return 42;
8 }
9
10 int main(int argc, char *argv[]) {
11 printf("Hello, world!\n");
12 printf("%d\n", func1());
13 return 0;
14 }
1010
1111 import TestGyp
1212
13 test = TestGyp.TestGyp()
13 test = TestGyp.TestGyp(workdir='workarea_all')
1414
1515 test.run_gyp('hello.gyp')
1616
1010
1111 import TestGyp
1212
13 test = TestGyp.TestGyp()
13 test = TestGyp.TestGyp(workdir='workarea_default')
1414
1515 test.run_gyp('hello.gyp')
1616
1010
1111 import TestGyp
1212
13 test = TestGyp.TestGyp()
13 test = TestGyp.TestGyp(workdir='workarea_target')
1414
1515 test.run_gyp('hello.gyp')
1616
1111
1212 test = TestGyp.TestGyp()
1313
14 if test.format == 'scons':
15 test.skip_test('TODO: http://code.google.com/p/gyp/issues/detail?id=176\n')
16
1417 test.run_gyp('includes.gyp', chdir='src')
1518
1619 test.relocate('src', 'relocate/src')
2225 Hello from inc.h
2326 Hello from include1.h
2427 Hello from subdir/inc2/include2.h
28 Hello from shadow2/shadow.h
2529 """
2630 test.run_built_executable('includes', stdout=expect, chdir='relocate/src')
2731
1111
1212 test = TestGyp.TestGyp()
1313
14 if test.format == 'scons':
15 test.skip_test('TODO: http://code.google.com/p/gyp/issues/detail?id=176\n')
16
1417 test.run_gyp('includes.gyp', chdir='src')
1518
1619 test.relocate('src', 'relocate/src')
2225 Hello from inc.h
2326 Hello from include1.h
2427 Hello from subdir/inc2/include2.h
28 Hello from shadow2/shadow.h
2529 """
2630 test.run_built_executable('includes', stdout=expect, chdir='relocate/src')
2731
22 #include "inc.h"
33 #include "include1.h"
44 #include "include2.h"
5 #include "shadow.h"
56
67 int main(int argc, char *argv[])
78 {
910 printf("Hello from %s\n", INC_STRING);
1011 printf("Hello from %s\n", INCLUDE1_STRING);
1112 printf("Hello from %s\n", INCLUDE2_STRING);
13 /* Test that include_dirs happen first: The gyp file has a -Ishadow1
14 cflag and an include_dir of shadow2. Including shadow.h should get
15 the shadow.h from the include_dir. */
16 printf("Hello from %s\n", SHADOW_STRING);
1217 return 0;
1318 }
99 'dependencies': [
1010 'subdir/subdir_includes.gyp:subdir_includes',
1111 ],
12 'cflags': [
13 '-Ishadow1',
14 ],
1215 'include_dirs': [
1316 '.',
1417 'inc1',
18 'shadow2',
1519 'subdir/inc2',
1620 ],
1721 'sources': [
0 #define SHADOW_STRING "shadow1/shadow.h"
0 #define SHADOW_STRING "shadow2/shadow.h"
407407 build_tool_list = [None, 'devenv.com']
408408
409409 def initialize_build_tool(self):
410 """
411 Initializes the Visual Studio .build_tool parameter, searching %PATH%
412 and %PATHEXT% for a devenv.{exe,bat,...} executable, and falling
413 back to a hard-coded default (on the current drive) if necessary.
410 """ Initializes the Visual Studio .build_tool and .uses_msbuild parameters.
411
412 We use the value specified by GYP_MSVS_VERSION. If not specified, we
413 search %PATH% and %PATHEXT% for a devenv.{exe,bat,...} executable.
414 Failing that, we search for likely deployment paths.
414415 """
415416 super(TestGypMSVS, self).initialize_build_tool()
416 if not self.build_tool:
417 # We didn't find 'devenv' on the path. Just hard-code a default,
418 # and revisit this if it becomes important.
419 possible = [
420 # Note: if you're using this, set GYP_MSVS_VERSION=2008
421 # to get the tests to pass.
422 ('C:\\Program Files (x86)',
423 'Microsoft Visual Studio 9.0', 'Common7', 'IDE', 'devenv.com'),
424 ('C:\\Program Files',
425 'Microsoft Visual Studio 9.0', 'Common7', 'IDE', 'devenv.com'),
426 ('C:\\Program Files (x86)',
427 'Microsoft Visual Studio 8', 'Common7', 'IDE', 'devenv.com'),
428 ('C:\\Program Files',
429 'Microsoft Visual Studio 8', 'Common7', 'IDE', 'devenv.com'),
430 ]
431 for build_tool in possible:
432 bt = os.path.join(*build_tool)
417 possible_roots = ['C:\\Program Files (x86)', 'C:\\Program Files']
418 possible_paths = {
419 '2010': r'Microsoft Visual Studio 10.0\Common7\IDE\devenv.com',
420 '2008': r'Microsoft Visual Studio 9.0\Common7\IDE\devenv.com',
421 '2005': r'Microsoft Visual Studio 8\Common7\IDE\devenv.com'}
422 msvs_version = os.environ.get('GYP_MSVS_VERSION', 'auto')
423 if msvs_version in possible_paths:
424 # Check that the path to the specified GYP_MSVS_VERSION exists.
425 path = possible_paths[msvs_version]
426 for r in possible_roots:
427 bt = os.path.join(r, path)
433428 if os.path.exists(bt):
434429 self.build_tool = bt
435 break
430 self.uses_msbuild = msvs_version >= '2010'
431 return
432 else:
433 print ('Warning: Environment variable GYP_MSVS_VERSION specifies "%s" '
434 'but corresponding "%s" was not found.' % (msvs_version, path))
435 if self.build_tool:
436 # We found 'devenv' on the path, use that and try to guess the version.
437 for version, path in possible_paths.iteritems():
438 if self.build_tool.find(path) >= 0:
439 self.uses_msbuild = version >= '2010'
440 return
441 else:
442 # If not, assume not MSBuild.
443 self.uses_msbuild = False
444 return
445 # Neither GYP_MSVS_VERSION nor the path help us out. Iterate through
446 # the choices looking for a match.
447 for version, path in possible_paths.iteritems():
448 for r in possible_roots:
449 bt = os.path.join(r, path)
450 if os.path.exists(bt):
451 self.build_tool = bt
452 self.uses_msbuild = msvs_version >= '2010'
453 return
454 print 'Error: could not find devenv'
455 sys.exit(1)
436456 def build(self, gyp_file, target=None, rebuild=False, **kw):
437457 """
438458 Runs a Visual Studio build using the configuration generated
457477 def up_to_date(self, gyp_file, target=None, **kw):
458478 """
459479 Verifies that a build of the specified Visual Studio target is up to date.
480
481 Beware that VS2010 will behave strangely if you build under
482 C:\USERS\yourname\AppData\Local. It will cause needless work. The ouptut
483 will be "1 succeeded and 0 up to date". MSBuild tracing reveals that:
484 "Project 'C:\Users\...\AppData\Local\...vcxproj' not up to date because
485 'C:\PROGRAM FILES (X86)\MICROSOFT VISUAL STUDIO 10.0\VC\BIN\1033\CLUI.DLL'
486 was modified at 02/21/2011 17:03:30, which is newer than '' which was
487 modified at 01/01/0001 00:00:00.
488
489 The workaround is to specify a workdir when instantiating the test, e.g.
490 test = TestGyp.TestGyp(workdir='workarea')
460491 """
461492 result = self.build(gyp_file, target, **kw)
462493 if not result:
463494 stdout = self.stdout()
495
464496 m = self.up_to_date_re.search(stdout)
465 if not m or m.group(1) == '0':
497 up_to_date = m and m.group(1) == '1'
498 if not up_to_date:
466499 self.report_not_up_to_date()
467500 self.fail_test()
468501 return result
594627 re.compile('__________Shutting down distcc-pump include server\n', re.S),
595628 ]
596629
597 up_to_date_ending = 'Checking Dependencies...\n** BUILD SUCCEEDED **\n'
630 up_to_date_endings = (
631 'Checking Dependencies...\n** BUILD SUCCEEDED **\n', # Xcode 3.0/3.1
632 'Check dependencies\n** BUILD SUCCEEDED **\n\n', # Xcode 3.2
633 )
598634
599635 def build(self, gyp_file, target=None, **kw):
600636 """
625661 output = self.stdout()
626662 for expression in self.strip_up_to_date_expressions:
627663 output = expression.sub('', output)
628 if not output.endswith(self.up_to_date_ending):
664 if not output.endswith(self.up_to_date_endings):
629665 self.report_not_up_to_date()
630666 self.fail_test()
631667 return result
0 #!/usr/bin/env python
1
2 # Copyright (c) 2010 Google Inc. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 """
7 Verifies that .so files that are order only dependencies are specified by
8 their install location rather than by their alias.
9 """
10
11 # Python 2.5 needs this for the with statement.
12 from __future__ import with_statement
13
14 import os
15 import TestGyp
16
17 test = TestGyp.TestGyp(formats=['make'])
18
19 test.run_gyp('shared_dependency.gyp',
20 chdir='src')
21 test.relocate('src', 'relocate/src')
22
23 test.build('shared_dependency.gyp', test.ALL, chdir='relocate/src')
24
25 with open('relocate/src/Makefile') as makefile:
26 make_contents = makefile.read()
27
28 # If we remove the code to generate lib1, Make should still be able
29 # to build lib2 since lib1.so already exists.
30 make_contents = make_contents.replace('include lib1.target.mk', '')
31 with open('relocate/src/Makefile', 'w') as makefile:
32 makefile.write(make_contents)
33
34 test.build('shared_dependency.gyp', test.ALL, chdir='relocate/src')
35
36 test.pass_test()
0 # Copyright (c) 2009 Google Inc. All rights reserved.
1 # Use of this source code is governed by a BSD-style license that can be
2 # found in the LICENSE file.
3
4 {
5 'targets': [
6 {
7 'target_name': 'lib1',
8 'type': 'shared_library',
9 'sources': [
10 'lib1.c',
11 ],
12 },
13 {
14 'target_name': 'lib2',
15 'type': 'shared_library',
16 'sources': [
17 'lib2.c',
18 ],
19 'dependencies': [
20 'lib1',
21 ],
22 },
23 ],
24 'conditions': [
25 ['OS=="linux"', {
26 'target_defaults': {
27 # Support 64-bit shared libs (also works fine for 32-bit).
28 'cflags': ['-fPIC'],
29 },
30 }],
31 ],
32 }
0 void extra();
1
2 int main(int argc, char** argv) {
3 extra();
4 return 0;
5 }
0 #include <stdio.h>
1
2 void extra() {
3 printf("PASS\n");
4 }
0 #!/usr/bin/env python
1
2 # Copyright (c) 2009 Google Inc. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 """
7 Put an object file on the sources list.
8 Expect the result to link ok.
9 """
10
11 import TestGyp
12
13 # Currently only works under the make build.
14 test = TestGyp.TestGyp(formats=['make'])
15
16 test.run_gyp('link-objects.gyp')
17
18 test.build('link-objects.gyp', test.ALL)
19
20 test.run_built_executable('link-objects', stdout="PASS\n")
21
22 test.up_to_date('link-objects.gyp', test.ALL)
23
24 test.pass_test()
0 # Copyright (c) 2009 Google Inc. All rights reserved.
1 # Use of this source code is governed by a BSD-style license that can be
2 # found in the LICENSE file.
3
4 {
5 'targets': [
6 {
7 'target_name': 'link-objects',
8 'type': 'executable',
9 'actions': [
10 {
11 'action_name': 'build extra object',
12 'inputs': ['extra.c'],
13 'outputs': ['extra.o'],
14 'action': ['gcc', '-o', 'extra.o', '-c', 'extra.c'],
15 'process_outputs_as_sources': 1,
16 },
17 ],
18 'sources': [
19 'base.c',
20 ],
21 },
22 ],
23 }
0 # Copyright (c) 2009 Google Inc. All rights reserved.
1 # Use of this source code is governed by a BSD-style license that can be
2 # found in the LICENSE file.
3
4 {
5 'targets': [
6 {
7 'target_name': 'main',
8 'type': 'executable',
9 'sources': [
10 'main.cc',
11 ],
12 },
13 ],
14 }
0 #!/usr/bin/env python
1
2 # Copyright (c) 2009 Google Inc. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 """
7 Verifies that .d files and all.deps are properly generated.
8 """
9
10 import os
11 import TestGyp
12
13 # .d files are only used by the make build.
14 test = TestGyp.TestGyp(formats=['make'])
15
16 test.run_gyp('dependencies.gyp')
17
18 test.build('dependencies.gyp', test.ALL)
19
20 deps_file = test.built_file_path(".deps/out/Default/obj.target/main/main.o.d")
21 test.must_contain(deps_file, "main.h")
22
23 # Build a second time to make sure we generate all.deps.
24 test.build('dependencies.gyp', test.ALL)
25
26 all_deps_file = test.built_file_path(".deps/all.deps")
27 test.must_contain(all_deps_file, "main.h")
28 test.must_contain(all_deps_file, "cmd_")
29
30 test.pass_test()
0 #!/usr/bin/env python
1
2 # Copyright (c) 2010 Google Inc. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 """
7 Tests the use of the NO_LOAD flag which makes loading sub .mk files
8 optional.
9 """
10
11 # Python 2.5 needs this for the with statement.
12 from __future__ import with_statement
13
14 import os
15 import TestGyp
16
17 test = TestGyp.TestGyp(formats=['make'])
18
19 test.run_gyp('all.gyp', chdir='noload')
20
21 test.relocate('noload', 'relocate/noload')
22
23 test.build('build/all.gyp', test.ALL, chdir='relocate/noload')
24 test.run_built_executable('exe', chdir='relocate/noload',
25 stdout='Hello from shared.c.\n')
26
27 # Just sanity test that NO_LOAD=lib doesn't break anything.
28 test.build('build/all.gyp', test.ALL, chdir='relocate/noload',
29 arguments=['NO_LOAD=lib'])
30 test.run_built_executable('exe', chdir='relocate/noload',
31 stdout='Hello from shared.c.\n')
32 test.build('build/all.gyp', test.ALL, chdir='relocate/noload',
33 arguments=['NO_LOAD=z'])
34 test.run_built_executable('exe', chdir='relocate/noload',
35 stdout='Hello from shared.c.\n')
36
37 # Make sure we can rebuild without reloading the sub .mk file.
38 with open('relocate/noload/main.c', 'a') as src_file:
39 src_file.write("\n")
40 test.build('build/all.gyp', test.ALL, chdir='relocate/noload',
41 arguments=['NO_LOAD=lib'])
42 test.run_built_executable('exe', chdir='relocate/noload',
43 stdout='Hello from shared.c.\n')
44
45 # Change shared.c, but verify that it doesn't get rebuild if we don't load it.
46 with open('relocate/noload/lib/shared.c', 'w') as shared_file:
47 shared_file.write(
48 '#include "shared.h"\n'
49 'const char kSharedStr[] = "modified";\n'
50 )
51 test.build('build/all.gyp', test.ALL, chdir='relocate/noload',
52 arguments=['NO_LOAD=lib'])
53 test.run_built_executable('exe', chdir='relocate/noload',
54 stdout='Hello from shared.c.\n')
55
56 test.pass_test()
0 /* Copyright (c) 2009 Google Inc. All rights reserved.
1 * Use of this source code is governed by a BSD-style license that can be
2 * found in the LICENSE file. */
3
4 #include <stdio.h>
5
6 #include "main.h"
7
8 int main(int argc, char *argv[]) {
9 printf("hello world\n");
10 return 0;
11 }
(New empty file)
0 # Copyright (c) 2010 Google Inc. All rights reserved.
1 # Use of this source code is governed by a BSD-style license that can be
2 # found in the LICENSE file.
3
4 {
5 'targets': [
6 {
7 'target_name': 'exe',
8 'type': 'executable',
9 'sources': [
10 'main.c',
11 ],
12 'dependencies': [
13 'lib/shared.gyp:shared',
14 ],
15 },
16 ],
17 }
0 #include "shared.h"
1
2 const char kSharedStr[] = "shared.c";
0 # Copyright (c) 2009 Google Inc. All rights reserved.
1 # Use of this source code is governed by a BSD-style license that can be
2 # found in the LICENSE file.
3
4 {
5 'targets': [
6 {
7 'target_name': 'shared',
8 'type': 'shared_library',
9 'sources': [
10 'shared.c',
11 'shared.h',
12 ],
13 },
14 ],
15 }
0 extern const char kSharedStr[];
0 #include <stdio.h>
1
2 #include "lib/shared.h"
3
4 int main(int argc, char *argv[])
5 {
6 printf("Hello from %s.\n", kSharedStr);
7 return 0;
8 }
1313 #if defined(PLATFORM_WIN)
1414 #define MODULE_SUFFIX ".dll"
1515 #elif defined(PLATFORM_MAC)
16 #define MODULE_SUFFIX ".dylib"
16 #define MODULE_SUFFIX ".so"
1717 #elif defined(PLATFORM_LINUX)
1818 #define MODULE_SUFFIX ".so"
1919 #endif
0 #!/usr/bin/env python
1
2 # Copyright (c) 2011 Google Inc. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 """
7 Verifies that precompiled headers can be specified.
8 """
9
10 import TestGyp
11
12 test = TestGyp.TestGyp(formats=['msvs'], workdir='workarea_all')
13
14 test.run_gyp('hello.gyp')
15
16 test.build('hello.gyp', 'hello')
17
18 test.run_built_executable('hello', stdout="Hello, world!\nHello, two!\n")
19
20 test.up_to_date('hello.gyp', test.ALL)
21
22 test.pass_test()
0 /* Copyright (c) 2011 Google Inc. All rights reserved.
1 * Use of this source code is governed by a BSD-style license that can be
2 * found in the LICENSE file. */
3
4 // Note the abscence of a stdio.h include. This will be inserted because of the
5 // precompiled header.
6
7 extern int hello2();
8
9 int main(int argc, char *argv[]) {
10 printf("Hello, world!\n");
11 hello2();
12 return 0;
13 }
0 # Copyright (c) 2011 Google Inc. All rights reserved.
1 # Use of this source code is governed by a BSD-style license that can be
2 # found in the LICENSE file.
3
4 {
5 'targets': [
6 {
7 'target_name': 'hello',
8 'type': 'executable',
9 'sources': [
10 'hello.c',
11 'hello2.c',
12 'precomp.c',
13 ],
14 'msvs_precompiled_header': 'stdio.h',
15 'msvs_precompiled_source': 'precomp.c',
16 },
17 ],
18 }
0 /* Copyright (c) 2011 Google Inc. All rights reserved.
1 * Use of this source code is governed by a BSD-style license that can be
2 * found in the LICENSE file. */
3
4 // Unlike hello.c, this file specifies the headers.
5
6 #include <windows.h>
7 #include <stdio.h>
8
9 int hello2() {
10 printf("Hello, two!\n");
11 return 0;
12 }
0 /* Copyright (c) 2011 Google Inc. All rights reserved.
1 * Use of this source code is governed by a BSD-style license that can be
2 * found in the LICENSE file. */
3
4 // The precompiled header does not have to be the first one in the file.
5
6 #include <windows.h>
7 #include <stdio.h>
4343 test.must_match('relocate/src/subdir2/file1.out', "Hello from file1.in\n")
4444 test.must_match('relocate/src/subdir2/file2.out', "Hello from file2.in\n")
4545
46 test.must_match('relocate/src/subdir2/file1.out2', "Hello from file1.in\n")
47 test.must_match('relocate/src/subdir2/file2.out2', "Hello from file2.in\n")
48
4649 test.pass_test()
4343 test.must_match('relocate/src/subdir2/file1.out', "Hello from file1.in\n")
4444 test.must_match('relocate/src/subdir2/file2.out', "Hello from file2.in\n")
4545
46 test.must_match('relocate/src/subdir2/file1.out2', "Hello from file1.in\n")
47 test.must_match('relocate/src/subdir2/file2.out2', "Hello from file2.in\n")
48
4649 test.pass_test()
88 'type': 'none',
99 'dependencies': [
1010 'subdir1/executable.gyp:*',
11 'subdir2/never_used.gyp:*',
12 'subdir2/no_inputs.gyp:*',
1113 'subdir2/none.gyp:*',
1214 'subdir3/executable2.gyp:*',
1315 ],
0 # Copyright (c) 2009 Google Inc. All rights reserved.
1 # Use of this source code is governed by a BSD-style license that can be
2 # found in the LICENSE file.
3
4 # Test that the case where there is a rule that doesn't apply to anything.
5 {
6 'targets': [
7 {
8 'target_name': 'files_no_input2',
9 'type': 'none',
10 'msvs_cygwin_shell': 0,
11 'sources': [
12 'file1.in',
13 'file2.in',
14 ],
15 'rules': [
16 {
17 'rule_name': 'copy_file3',
18 'extension': 'in2',
19 'outputs': [
20 '<(RULE_INPUT_ROOT).out3',
21 ],
22 'action': [
23 'python', '../copy-file.py', '<(RULE_INPUT_PATH)', '<@(_outputs)',
24 ],
25 'process_outputs_as_sources': 1,
26 },
27 ],
28 },
29 ],
30 }
0 # Copyright (c) 2009 Google Inc. All rights reserved.
1 # Use of this source code is governed by a BSD-style license that can be
2 # found in the LICENSE file.
3
4 # Test that the case where there are no inputs (other than the
5 # file the rule applies to).
6 {
7 'targets': [
8 {
9 'target_name': 'files_no_input',
10 'type': 'none',
11 'msvs_cygwin_shell': 0,
12 'sources': [
13 'file1.in',
14 'file2.in',
15 ],
16 'rules': [
17 {
18 'rule_name': 'copy_file2',
19 'extension': 'in',
20 'outputs': [
21 '<(RULE_INPUT_ROOT).out2',
22 ],
23 'action': [
24 'python', '../copy-file.py', '<(RULE_INPUT_PATH)', '<@(_outputs)',
25 ],
26 'process_outputs_as_sources': 1,
27 },
28 ],
29 },
30 ],
31 }
1010
1111 import TestGyp
1212
13 test = TestGyp.TestGyp()
14
15 if test.format == 'msvs':
16 msg = 'TODO: issue 120: disabled on MSVS due to test execution problems.\n'
17 test.skip_test(msg)
13 test = TestGyp.TestGyp(workdir='workarea_all')
1814
1915 test.run_gyp('same_target.gyp', chdir='src')
2016
1010
1111 import TestGyp
1212
13 test = TestGyp.TestGyp()
14
15 if test.format == 'msvs':
16 msg = 'TODO: issue 120: disabled on MSVS due to test execution problems.\n'
17 test.skip_test(msg)
13 test = TestGyp.TestGyp(workdir='workarea_default')
1814
1915 test.run_gyp('same_target.gyp', chdir='src')
2016
1212 {
1313 'rule_name': 'make_sources',
1414 'extension': 'in',
15 'msvs_external_rule': 1,
1615 'inputs': [
1716 'make-sources.py',
1817 ],
0 #!/usr/bin/env python
1
2 # Copyright (c) 2010 Google Inc. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 """
7 Check that duplicate targets in a directory gives an error.
8 """
9
10 import TestGyp
11
12 test = TestGyp.TestGyp()
13
14 # Require that gyp files with duplicate targets spit out an error.
15 test.run_gyp('all.gyp', chdir='src', status=1, stderr=None)
16
17 test.pass_test()
0 # Copyright (c) 2010 Google Inc. All rights reserved.
1 # Use of this source code is governed by a BSD-style license that can be
2 # found in the LICENSE file.
3
4 {
5 'targets': [
6 {
7 'target_name': 'all_exes',
8 'type': 'none',
9 'dependencies': [
10 'executable1.gyp:*',
11 'executable2.gyp:*',
12 ],
13 },
14 ],
15 }
0 # Copyright (c) 2010 Google Inc. All rights reserved.
1 # Use of this source code is governed by a BSD-style license that can be
2 # found in the LICENSE file.
3
4 {
5 'targets': [
6 {
7 'target_name': 'program',
8 'type': 'executable',
9 'sources': [
10 'main1.cc',
11 ],
12 },
13 ],
14 }
0 # Copyright (c) 2010 Google Inc. All rights reserved.
1 # Use of this source code is governed by a BSD-style license that can be
2 # found in the LICENSE file.
3
4 {
5 'targets': [
6 {
7 'target_name': 'program',
8 'type': 'executable',
9 'sources': [
10 'main2.cc',
11 ],
12 },
13 ],
14 }
0 #!/usr/bin/env python
1
2 # Copyright (c) 2011 Google Inc. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 """
7 Runs small tests.
8 """
9
10 import imp
11 import os
12 import sys
13 import unittest
14
15 import TestGyp
16
17
18 test = TestGyp.TestGyp()
19
20 # Add pylib/gyp to the import path (so tests can import their dependencies).
21 sys.path.append(os.path.join(test._cwd, 'pylib', 'gyp'))
22
23 # Add new test suites here.
24 files_to_test = [
25 'pylib/gyp/MSVSSettings_test.py',
26 'pylib/gyp/easy_xml_test.py',
27 ]
28
29 # Collect all the suites from the above files.
30 suites = []
31 for filename in files_to_test:
32 # Carve the module name out of the path.
33 name = os.path.splitext(os.path.split(filename)[1])[0]
34 # Find the complete module path.
35 full_filename = os.path.join(test._cwd, filename)
36 # Load the module.
37 module = imp.load_source(name, full_filename)
38 # Add it to the list of test suites.
39 suites.append(unittest.defaultTestLoader.loadTestsFromModule(module))
40 # Create combined suite.
41 all_tests = unittest.TestSuite(suites)
42
43 # Run all the tests.
44 result = unittest.TextTestRunner(verbosity=2).run(all_tests)
45 if result.failures or result.errors:
46 test.fail_test()
47
48 test.pass_test()
0 #!/usr/bin/env python
1
2 # Copyright (c) 2009 Google Inc. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 """
7 Verifies building a subsidiary dependent target from a .gyp file in a
8 subdirectory, without specifying an explicit output build directory,
9 and using the subdirectory's solution or project file as the entry point.
10 """
11
12 import TestGyp
13 import errno
14
15 test = TestGyp.TestGyp(formats=['make'])
16
17 # We want our Makefile to be one dir up from main.gyp.
18 test.run_gyp('main.gyp', '--toplevel-dir=..', chdir='src/sub1')
19
20 toplevel_dir = 'src'
21
22 test.build('all', chdir=toplevel_dir)
23
24 test.built_file_must_exist('prog1', type=test.EXECUTABLE, chdir=toplevel_dir)
25
26 test.run_built_executable('prog1',
27 chdir=toplevel_dir,
28 stdout="Hello from prog1.c\n")
29
30 test.pass_test()
0 # Copyright (c) 2009 Google Inc. All rights reserved.
1 # Use of this source code is governed by a BSD-style license that can be
2 # found in the LICENSE file.
3
4 {
5 'targets': [
6 {
7 'target_name': 'prog1',
8 'type': 'executable',
9 'dependencies': [
10 '<(DEPTH)/../sub2/prog2.gyp:prog2',
11 ],
12 'sources': [
13 'prog1.c',
14 ],
15 },
16 ],
17 }
0 #include <stdio.h>
1
2 int main(int argc, char *argv[])
3 {
4 printf("Hello from prog1.c\n");
5 return 0;
6 }
0 #include <stdio.h>
1
2 int main(int argc, char *argv[])
3 {
4 printf("Hello from prog2.c\n");
5 return 0;
6 }
0 # Copyright (c) 2009 Google Inc. All rights reserved.
1 # Use of this source code is governed by a BSD-style license that can be
2 # found in the LICENSE file.
3
4 {
5 'targets': [
6 {
7 'target_name': 'prog2',
8 'type': 'executable',
9 'sources': [
10 'prog2.c',
11 ],
12 },
13 ],
14 }
00 GENERAL: running with these options:
1 GENERAL: check: None
2 GENERAL: circular_check: True
3 GENERAL: debug: ['variables', 'general']
4 GENERAL: defines: None
5 GENERAL: depth: '.'
6 GENERAL: formats: ['gypd']
7 GENERAL: generator_flags: []
8 GENERAL: generator_output: None
9 GENERAL: includes: None
110 GENERAL: msvs_version: None
211 GENERAL: suffix: ''
3 GENERAL: includes: None
12 GENERAL: toplevel_dir: None
413 GENERAL: use_environment: True
5 GENERAL: depth: '.'
6 GENERAL: generator_flags: []
7 GENERAL: generator_output: None
8 GENERAL: formats: ['gypd']
9 GENERAL: debug: ['variables', 'general']
10 GENERAL: circular_check: True
11 GENERAL: check: None
12 GENERAL: defines: None
1314 GENERAL: cmdline_default_variables: {}
1415 GENERAL: generator_flags: {}
1516 VARIABLES: Expanding '0' to 0
00 GENERAL: running with these options:
1 GENERAL: check: None
2 GENERAL: circular_check: True
3 GENERAL: debug: ['variables', 'general']
4 GENERAL: defines: None
5 GENERAL: depth: '.'
6 GENERAL: formats: ['gypd']
7 GENERAL: generator_flags: []
8 GENERAL: generator_output: None
9 GENERAL: includes: None
110 GENERAL: msvs_version: None
211 GENERAL: suffix: ''
3 GENERAL: includes: None
12 GENERAL: toplevel_dir: None
413 GENERAL: use_environment: False
5 GENERAL: depth: '.'
6 GENERAL: generator_flags: []
7 GENERAL: generator_output: None
8 GENERAL: formats: ['gypd']
9 GENERAL: debug: ['variables', 'general']
10 GENERAL: circular_check: True
11 GENERAL: check: None
12 GENERAL: defines: None
1314 GENERAL: cmdline_default_variables: {}
1415 GENERAL: generator_flags: {}
1516 VARIABLES: Expanding '0' to 0
00 GENERAL: running with these options:
1 GENERAL: check: None
2 GENERAL: circular_check: True
3 GENERAL: debug: ['variables', 'general']
4 GENERAL: defines: None
5 GENERAL: depth: '.'
6 GENERAL: formats: ['gypd']
7 GENERAL: generator_flags: []
8 GENERAL: generator_output: None
9 GENERAL: includes: None
110 GENERAL: msvs_version: None
211 GENERAL: suffix: ''
3 GENERAL: includes: None
12 GENERAL: toplevel_dir: None
413 GENERAL: use_environment: True
5 GENERAL: depth: '.'
6 GENERAL: generator_flags: []
7 GENERAL: generator_output: None
8 GENERAL: formats: ['gypd']
9 GENERAL: debug: ['variables', 'general']
10 GENERAL: circular_check: True
11 GENERAL: check: None
12 GENERAL: defines: None
1314 GENERAL: cmdline_default_variables: {}
1415 GENERAL: generator_flags: {}
1516 VARIABLES: Expanding '0' to 0
00 GENERAL: running with these options:
1 GENERAL: check: None
2 GENERAL: circular_check: True
3 GENERAL: debug: ['variables', 'general']
4 GENERAL: defines: None
5 GENERAL: depth: '.'
6 GENERAL: formats: ['gypd']
7 GENERAL: generator_flags: []
8 GENERAL: generator_output: None
9 GENERAL: includes: None
110 GENERAL: msvs_version: None
211 GENERAL: suffix: ''
3 GENERAL: includes: None
12 GENERAL: toplevel_dir: None
413 GENERAL: use_environment: True
5 GENERAL: depth: '.'
6 GENERAL: generator_flags: []
7 GENERAL: generator_output: None
8 GENERAL: formats: ['gypd']
9 GENERAL: debug: ['variables', 'general']
10 GENERAL: circular_check: True
11 GENERAL: check: None
12 GENERAL: defines: None
1314 GENERAL: cmdline_default_variables: {}
1415 GENERAL: generator_flags: {}
1516 VARIABLES: Expanding 'exclude' to 'exclude'