redsnow 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +34 -0
- data/.gitmodules +3 -0
- data/.travis.yml +20 -0
- data/CHANGELOG.md +4 -0
- data/Gemfile +4 -0
- data/LICENSE +21 -0
- data/README.md +62 -0
- data/Rakefile +36 -0
- data/Vagrantfile +20 -0
- data/ext/snowcrash/Makefile +64 -0
- data/ext/snowcrash/Vagrantfile +20 -0
- data/ext/snowcrash/bin/snowcrash +0 -0
- data/ext/snowcrash/common.gypi +163 -0
- data/ext/snowcrash/config.gypi +10 -0
- data/ext/snowcrash/config.mk +5 -0
- data/ext/snowcrash/configure +213 -0
- data/ext/snowcrash/provisioning.sh +15 -0
- data/ext/snowcrash/snowcrash.gyp +141 -0
- data/ext/snowcrash/src/ActionParser.h +503 -0
- data/ext/snowcrash/src/AssetParser.h +215 -0
- data/ext/snowcrash/src/BlockUtility.h +186 -0
- data/ext/snowcrash/src/Blueprint.h +283 -0
- data/ext/snowcrash/src/BlueprintParser.h +347 -0
- data/ext/snowcrash/src/BlueprintParserCore.h +190 -0
- data/ext/snowcrash/src/BlueprintSection.h +140 -0
- data/ext/snowcrash/src/BlueprintUtility.h +126 -0
- data/ext/snowcrash/src/CBlueprint.cc +600 -0
- data/ext/snowcrash/src/CBlueprint.h +354 -0
- data/ext/snowcrash/src/CSourceAnnotation.cc +140 -0
- data/ext/snowcrash/src/CSourceAnnotation.h +106 -0
- data/ext/snowcrash/src/CodeBlockUtility.h +189 -0
- data/ext/snowcrash/src/DescriptionSectionUtility.h +156 -0
- data/ext/snowcrash/src/HTTP.cc +46 -0
- data/ext/snowcrash/src/HTTP.h +105 -0
- data/ext/snowcrash/src/HeaderParser.h +289 -0
- data/ext/snowcrash/src/ListBlockUtility.h +273 -0
- data/ext/snowcrash/src/ListUtility.h +95 -0
- data/ext/snowcrash/src/MarkdownBlock.cc +176 -0
- data/ext/snowcrash/src/MarkdownBlock.h +93 -0
- data/ext/snowcrash/src/MarkdownParser.cc +266 -0
- data/ext/snowcrash/src/MarkdownParser.h +88 -0
- data/ext/snowcrash/src/ParameterDefinitonParser.h +570 -0
- data/ext/snowcrash/src/ParametersParser.h +252 -0
- data/ext/snowcrash/src/Parser.cc +71 -0
- data/ext/snowcrash/src/Parser.h +29 -0
- data/ext/snowcrash/src/ParserCore.cc +120 -0
- data/ext/snowcrash/src/ParserCore.h +82 -0
- data/ext/snowcrash/src/PayloadParser.h +672 -0
- data/ext/snowcrash/src/Platform.h +54 -0
- data/ext/snowcrash/src/RegexMatch.h +32 -0
- data/ext/snowcrash/src/ResourceGroupParser.h +195 -0
- data/ext/snowcrash/src/ResourceParser.h +584 -0
- data/ext/snowcrash/src/SectionUtility.h +142 -0
- data/ext/snowcrash/src/Serialize.cc +52 -0
- data/ext/snowcrash/src/Serialize.h +69 -0
- data/ext/snowcrash/src/SerializeJSON.cc +601 -0
- data/ext/snowcrash/src/SerializeJSON.h +21 -0
- data/ext/snowcrash/src/SerializeYAML.cc +336 -0
- data/ext/snowcrash/src/SerializeYAML.h +21 -0
- data/ext/snowcrash/src/SourceAnnotation.h +177 -0
- data/ext/snowcrash/src/StringUtility.h +109 -0
- data/ext/snowcrash/src/SymbolTable.h +83 -0
- data/ext/snowcrash/src/UriTemplateParser.cc +195 -0
- data/ext/snowcrash/src/UriTemplateParser.h +243 -0
- data/ext/snowcrash/src/Version.h +39 -0
- data/ext/snowcrash/src/csnowcrash.cc +23 -0
- data/ext/snowcrash/src/csnowcrash.h +38 -0
- data/ext/snowcrash/src/posix/RegexMatch.cc +99 -0
- data/ext/snowcrash/src/snowcrash.cc +18 -0
- data/ext/snowcrash/src/snowcrash.h +41 -0
- data/ext/snowcrash/src/snowcrash/snowcrash.cc +170 -0
- data/ext/snowcrash/src/win/RegexMatch.cc +78 -0
- data/ext/snowcrash/sundown/CONTRIBUTING.md +10 -0
- data/ext/snowcrash/sundown/Makefile +83 -0
- data/ext/snowcrash/sundown/Makefile.win +33 -0
- data/ext/snowcrash/sundown/examples/smartypants.c +72 -0
- data/ext/snowcrash/sundown/examples/sundown.c +80 -0
- data/ext/snowcrash/sundown/html/houdini.h +37 -0
- data/ext/snowcrash/sundown/html/houdini_href_e.c +108 -0
- data/ext/snowcrash/sundown/html/houdini_html_e.c +84 -0
- data/ext/snowcrash/sundown/html/html.c +647 -0
- data/ext/snowcrash/sundown/html/html.h +77 -0
- data/ext/snowcrash/sundown/html/html_smartypants.c +389 -0
- data/ext/snowcrash/sundown/html_block_names.txt +25 -0
- data/ext/snowcrash/sundown/src/autolink.c +297 -0
- data/ext/snowcrash/sundown/src/autolink.h +51 -0
- data/ext/snowcrash/sundown/src/buffer.c +225 -0
- data/ext/snowcrash/sundown/src/buffer.h +96 -0
- data/ext/snowcrash/sundown/src/html_blocks.h +206 -0
- data/ext/snowcrash/sundown/src/markdown.c +2701 -0
- data/ext/snowcrash/sundown/src/markdown.h +147 -0
- data/ext/snowcrash/sundown/src/src_map.c +200 -0
- data/ext/snowcrash/sundown/src/src_map.h +58 -0
- data/ext/snowcrash/sundown/src/stack.c +81 -0
- data/ext/snowcrash/sundown/src/stack.h +29 -0
- data/ext/snowcrash/sundown/sundown.def +20 -0
- data/ext/snowcrash/tools/gyp/AUTHORS +11 -0
- data/ext/snowcrash/tools/gyp/DEPS +24 -0
- data/ext/snowcrash/tools/gyp/OWNERS +1 -0
- data/ext/snowcrash/tools/gyp/PRESUBMIT.py +120 -0
- data/ext/snowcrash/tools/gyp/buildbot/buildbot_run.py +190 -0
- data/ext/snowcrash/tools/gyp/codereview.settings +10 -0
- data/ext/snowcrash/tools/gyp/data/win/large-pdb-shim.cc +12 -0
- data/ext/snowcrash/tools/gyp/gyp +8 -0
- data/ext/snowcrash/tools/gyp/gyp.bat +5 -0
- data/ext/snowcrash/tools/gyp/gyp_main.py +18 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/MSVSNew.py +340 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/MSVSProject.py +208 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/MSVSSettings.py +1063 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/MSVSToolFile.py +58 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/MSVSUserFile.py +147 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/MSVSUtil.py +267 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/MSVSVersion.py +409 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/__init__.py +537 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/__init__.pyc +0 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/common.py +521 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/common.pyc +0 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/easy_xml.py +157 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/flock_tool.py +49 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/generator/__init__.py +0 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/generator/__init__.pyc +0 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/generator/android.py +1069 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/generator/cmake.py +1143 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/generator/dump_dependency_json.py +81 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/generator/eclipse.py +335 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/generator/gypd.py +87 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/generator/gypsh.py +56 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/generator/make.py +2181 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/generator/make.pyc +0 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/generator/msvs.py +3335 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/generator/ninja.py +2156 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/generator/xcode.py +1224 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/generator/xcode.pyc +0 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/input.py +2809 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/input.pyc +0 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/mac_tool.py +510 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/msvs_emulation.py +972 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/ninja_syntax.py +160 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/ordered_dict.py +289 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/win_tool.py +292 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/xcode_emulation.py +1440 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/xcode_emulation.pyc +0 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/xcodeproj_file.py +2889 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/xcodeproj_file.pyc +0 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/xml_fix.py +69 -0
- data/ext/snowcrash/tools/gyp/pylintrc +307 -0
- data/ext/snowcrash/tools/gyp/samples/samples +81 -0
- data/ext/snowcrash/tools/gyp/samples/samples.bat +5 -0
- data/ext/snowcrash/tools/gyp/setup.py +19 -0
- data/ext/snowcrash/tools/gyp/tools/Xcode/Specifications/gyp.pbfilespec +27 -0
- data/ext/snowcrash/tools/gyp/tools/Xcode/Specifications/gyp.xclangspec +226 -0
- data/ext/snowcrash/tools/gyp/tools/emacs/gyp.el +252 -0
- data/ext/snowcrash/tools/gyp/tools/graphviz.py +100 -0
- data/ext/snowcrash/tools/gyp/tools/pretty_gyp.py +155 -0
- data/ext/snowcrash/tools/gyp/tools/pretty_sln.py +168 -0
- data/ext/snowcrash/tools/gyp/tools/pretty_vcproj.py +329 -0
- data/ext/snowcrash/tools/homebrew/snowcrash.rb +11 -0
- data/ext/snowcrash/vcbuild.bat +184 -0
- data/lib/redsnow.rb +31 -0
- data/lib/redsnow/binding.rb +132 -0
- data/lib/redsnow/blueprint.rb +365 -0
- data/lib/redsnow/object.rb +18 -0
- data/lib/redsnow/parseresult.rb +107 -0
- data/lib/redsnow/version.rb +4 -0
- data/provisioning.sh +20 -0
- data/redsnow.gemspec +35 -0
- data/test/_helper.rb +15 -0
- data/test/fixtures/sample-api-ast.json +97 -0
- data/test/fixtures/sample-api.apib +20 -0
- data/test/redsnow_binding_test.rb +35 -0
- data/test/redsnow_parseresult_test.rb +50 -0
- data/test/redsnow_test.rb +285 -0
- metadata +358 -0
@@ -0,0 +1,409 @@
|
|
1
|
+
# Copyright (c) 2013 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
|
+
"""Handle version information related to Visual Stuio."""
|
6
|
+
|
7
|
+
import errno
|
8
|
+
import os
|
9
|
+
import re
|
10
|
+
import subprocess
|
11
|
+
import sys
|
12
|
+
import gyp
|
13
|
+
import glob
|
14
|
+
|
15
|
+
|
16
|
+
class VisualStudioVersion(object):
|
17
|
+
"""Information regarding a version of Visual Studio."""
|
18
|
+
|
19
|
+
def __init__(self, short_name, description,
|
20
|
+
solution_version, project_version, flat_sln, uses_vcxproj,
|
21
|
+
path, sdk_based, default_toolset=None):
|
22
|
+
self.short_name = short_name
|
23
|
+
self.description = description
|
24
|
+
self.solution_version = solution_version
|
25
|
+
self.project_version = project_version
|
26
|
+
self.flat_sln = flat_sln
|
27
|
+
self.uses_vcxproj = uses_vcxproj
|
28
|
+
self.path = path
|
29
|
+
self.sdk_based = sdk_based
|
30
|
+
self.default_toolset = default_toolset
|
31
|
+
|
32
|
+
def ShortName(self):
|
33
|
+
return self.short_name
|
34
|
+
|
35
|
+
def Description(self):
|
36
|
+
"""Get the full description of the version."""
|
37
|
+
return self.description
|
38
|
+
|
39
|
+
def SolutionVersion(self):
|
40
|
+
"""Get the version number of the sln files."""
|
41
|
+
return self.solution_version
|
42
|
+
|
43
|
+
def ProjectVersion(self):
|
44
|
+
"""Get the version number of the vcproj or vcxproj files."""
|
45
|
+
return self.project_version
|
46
|
+
|
47
|
+
def FlatSolution(self):
|
48
|
+
return self.flat_sln
|
49
|
+
|
50
|
+
def UsesVcxproj(self):
|
51
|
+
"""Returns true if this version uses a vcxproj file."""
|
52
|
+
return self.uses_vcxproj
|
53
|
+
|
54
|
+
def ProjectExtension(self):
|
55
|
+
"""Returns the file extension for the project."""
|
56
|
+
return self.uses_vcxproj and '.vcxproj' or '.vcproj'
|
57
|
+
|
58
|
+
def Path(self):
|
59
|
+
"""Returns the path to Visual Studio installation."""
|
60
|
+
return self.path
|
61
|
+
|
62
|
+
def ToolPath(self, tool):
|
63
|
+
"""Returns the path to a given compiler tool. """
|
64
|
+
return os.path.normpath(os.path.join(self.path, "VC/bin", tool))
|
65
|
+
|
66
|
+
def DefaultToolset(self):
|
67
|
+
"""Returns the msbuild toolset version that will be used in the absence
|
68
|
+
of a user override."""
|
69
|
+
return self.default_toolset
|
70
|
+
|
71
|
+
def SetupScript(self, target_arch):
|
72
|
+
"""Returns a command (with arguments) to be used to set up the
|
73
|
+
environment."""
|
74
|
+
# Check if we are running in the SDK command line environment and use
|
75
|
+
# the setup script from the SDK if so. |target_arch| should be either
|
76
|
+
# 'x86' or 'x64'.
|
77
|
+
assert target_arch in ('x86', 'x64')
|
78
|
+
sdk_dir = os.environ.get('WindowsSDKDir')
|
79
|
+
if self.sdk_based and sdk_dir:
|
80
|
+
return [os.path.normpath(os.path.join(sdk_dir, 'Bin/SetEnv.Cmd')),
|
81
|
+
'/' + target_arch]
|
82
|
+
else:
|
83
|
+
# We don't use VC/vcvarsall.bat for x86 because vcvarsall calls
|
84
|
+
# vcvars32, which it can only find if VS??COMNTOOLS is set, which it
|
85
|
+
# isn't always.
|
86
|
+
if target_arch == 'x86':
|
87
|
+
if self.short_name == '2013' and (
|
88
|
+
os.environ.get('PROCESSOR_ARCHITECTURE') == 'AMD64' or
|
89
|
+
os.environ.get('PROCESSOR_ARCHITEW6432') == 'AMD64'):
|
90
|
+
# VS2013 non-Express has a x64-x86 cross that we want to prefer.
|
91
|
+
return [os.path.normpath(
|
92
|
+
os.path.join(self.path, 'VC/vcvarsall.bat')), 'amd64_x86']
|
93
|
+
# Otherwise, the standard x86 compiler.
|
94
|
+
return [os.path.normpath(
|
95
|
+
os.path.join(self.path, 'Common7/Tools/vsvars32.bat'))]
|
96
|
+
else:
|
97
|
+
assert target_arch == 'x64'
|
98
|
+
arg = 'x86_amd64'
|
99
|
+
# Use the 64-on-64 compiler if we're not using an express
|
100
|
+
# edition and we're running on a 64bit OS.
|
101
|
+
if self.short_name[-1] != 'e' and (
|
102
|
+
os.environ.get('PROCESSOR_ARCHITECTURE') == 'AMD64' or
|
103
|
+
os.environ.get('PROCESSOR_ARCHITEW6432') == 'AMD64'):
|
104
|
+
arg = 'amd64'
|
105
|
+
return [os.path.normpath(
|
106
|
+
os.path.join(self.path, 'VC/vcvarsall.bat')), arg]
|
107
|
+
|
108
|
+
|
109
|
+
def _RegistryQueryBase(sysdir, key, value):
|
110
|
+
"""Use reg.exe to read a particular key.
|
111
|
+
|
112
|
+
While ideally we might use the win32 module, we would like gyp to be
|
113
|
+
python neutral, so for instance cygwin python lacks this module.
|
114
|
+
|
115
|
+
Arguments:
|
116
|
+
sysdir: The system subdirectory to attempt to launch reg.exe from.
|
117
|
+
key: The registry key to read from.
|
118
|
+
value: The particular value to read.
|
119
|
+
Return:
|
120
|
+
stdout from reg.exe, or None for failure.
|
121
|
+
"""
|
122
|
+
# Skip if not on Windows or Python Win32 setup issue
|
123
|
+
if sys.platform not in ('win32', 'cygwin'):
|
124
|
+
return None
|
125
|
+
# Setup params to pass to and attempt to launch reg.exe
|
126
|
+
cmd = [os.path.join(os.environ.get('WINDIR', ''), sysdir, 'reg.exe'),
|
127
|
+
'query', key]
|
128
|
+
if value:
|
129
|
+
cmd.extend(['/v', value])
|
130
|
+
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
131
|
+
# Obtain the stdout from reg.exe, reading to the end so p.returncode is valid
|
132
|
+
# Note that the error text may be in [1] in some cases
|
133
|
+
text = p.communicate()[0]
|
134
|
+
# Check return code from reg.exe; officially 0==success and 1==error
|
135
|
+
if p.returncode:
|
136
|
+
return None
|
137
|
+
return text
|
138
|
+
|
139
|
+
|
140
|
+
def _RegistryQuery(key, value=None):
|
141
|
+
"""Use reg.exe to read a particular key through _RegistryQueryBase.
|
142
|
+
|
143
|
+
First tries to launch from %WinDir%\Sysnative to avoid WoW64 redirection. If
|
144
|
+
that fails, it falls back to System32. Sysnative is available on Vista and
|
145
|
+
up and available on Windows Server 2003 and XP through KB patch 942589. Note
|
146
|
+
that Sysnative will always fail if using 64-bit python due to it being a
|
147
|
+
virtual directory and System32 will work correctly in the first place.
|
148
|
+
|
149
|
+
KB 942589 - http://support.microsoft.com/kb/942589/en-us.
|
150
|
+
|
151
|
+
Arguments:
|
152
|
+
key: The registry key.
|
153
|
+
value: The particular registry value to read (optional).
|
154
|
+
Return:
|
155
|
+
stdout from reg.exe, or None for failure.
|
156
|
+
"""
|
157
|
+
text = None
|
158
|
+
try:
|
159
|
+
text = _RegistryQueryBase('Sysnative', key, value)
|
160
|
+
except OSError, e:
|
161
|
+
if e.errno == errno.ENOENT:
|
162
|
+
text = _RegistryQueryBase('System32', key, value)
|
163
|
+
else:
|
164
|
+
raise
|
165
|
+
return text
|
166
|
+
|
167
|
+
|
168
|
+
def _RegistryGetValue(key, value):
|
169
|
+
"""Use reg.exe to obtain the value of a registry key.
|
170
|
+
|
171
|
+
Args:
|
172
|
+
key: The registry key.
|
173
|
+
value: The particular registry value to read.
|
174
|
+
Return:
|
175
|
+
contents of the registry key's value, or None on failure.
|
176
|
+
"""
|
177
|
+
text = _RegistryQuery(key, value)
|
178
|
+
if not text:
|
179
|
+
return None
|
180
|
+
# Extract value.
|
181
|
+
match = re.search(r'REG_\w+\s+([^\r]+)\r\n', text)
|
182
|
+
if not match:
|
183
|
+
return None
|
184
|
+
return match.group(1)
|
185
|
+
|
186
|
+
|
187
|
+
def _RegistryKeyExists(key):
|
188
|
+
"""Use reg.exe to see if a key exists.
|
189
|
+
|
190
|
+
Args:
|
191
|
+
key: The registry key to check.
|
192
|
+
Return:
|
193
|
+
True if the key exists
|
194
|
+
"""
|
195
|
+
if not _RegistryQuery(key):
|
196
|
+
return False
|
197
|
+
return True
|
198
|
+
|
199
|
+
|
200
|
+
def _CreateVersion(name, path, sdk_based=False):
|
201
|
+
"""Sets up MSVS project generation.
|
202
|
+
|
203
|
+
Setup is based off the GYP_MSVS_VERSION environment variable or whatever is
|
204
|
+
autodetected if GYP_MSVS_VERSION is not explicitly specified. If a version is
|
205
|
+
passed in that doesn't match a value in versions python will throw a error.
|
206
|
+
"""
|
207
|
+
if path:
|
208
|
+
path = os.path.normpath(path)
|
209
|
+
versions = {
|
210
|
+
'2013': VisualStudioVersion('2013',
|
211
|
+
'Visual Studio 2013',
|
212
|
+
solution_version='13.00',
|
213
|
+
project_version='12.0',
|
214
|
+
flat_sln=False,
|
215
|
+
uses_vcxproj=True,
|
216
|
+
path=path,
|
217
|
+
sdk_based=sdk_based,
|
218
|
+
default_toolset='v120'),
|
219
|
+
'2013e': VisualStudioVersion('2013e',
|
220
|
+
'Visual Studio 2013',
|
221
|
+
solution_version='13.00',
|
222
|
+
project_version='12.0',
|
223
|
+
flat_sln=True,
|
224
|
+
uses_vcxproj=True,
|
225
|
+
path=path,
|
226
|
+
sdk_based=sdk_based,
|
227
|
+
default_toolset='v120'),
|
228
|
+
'2012': VisualStudioVersion('2012',
|
229
|
+
'Visual Studio 2012',
|
230
|
+
solution_version='12.00',
|
231
|
+
project_version='4.0',
|
232
|
+
flat_sln=False,
|
233
|
+
uses_vcxproj=True,
|
234
|
+
path=path,
|
235
|
+
sdk_based=sdk_based,
|
236
|
+
default_toolset='v110'),
|
237
|
+
'2012e': VisualStudioVersion('2012e',
|
238
|
+
'Visual Studio 2012',
|
239
|
+
solution_version='12.00',
|
240
|
+
project_version='4.0',
|
241
|
+
flat_sln=True,
|
242
|
+
uses_vcxproj=True,
|
243
|
+
path=path,
|
244
|
+
sdk_based=sdk_based,
|
245
|
+
default_toolset='v110'),
|
246
|
+
'2010': VisualStudioVersion('2010',
|
247
|
+
'Visual Studio 2010',
|
248
|
+
solution_version='11.00',
|
249
|
+
project_version='4.0',
|
250
|
+
flat_sln=False,
|
251
|
+
uses_vcxproj=True,
|
252
|
+
path=path,
|
253
|
+
sdk_based=sdk_based),
|
254
|
+
'2010e': VisualStudioVersion('2010e',
|
255
|
+
'Visual C++ Express 2010',
|
256
|
+
solution_version='11.00',
|
257
|
+
project_version='4.0',
|
258
|
+
flat_sln=True,
|
259
|
+
uses_vcxproj=True,
|
260
|
+
path=path,
|
261
|
+
sdk_based=sdk_based),
|
262
|
+
'2008': VisualStudioVersion('2008',
|
263
|
+
'Visual Studio 2008',
|
264
|
+
solution_version='10.00',
|
265
|
+
project_version='9.00',
|
266
|
+
flat_sln=False,
|
267
|
+
uses_vcxproj=False,
|
268
|
+
path=path,
|
269
|
+
sdk_based=sdk_based),
|
270
|
+
'2008e': VisualStudioVersion('2008e',
|
271
|
+
'Visual Studio 2008',
|
272
|
+
solution_version='10.00',
|
273
|
+
project_version='9.00',
|
274
|
+
flat_sln=True,
|
275
|
+
uses_vcxproj=False,
|
276
|
+
path=path,
|
277
|
+
sdk_based=sdk_based),
|
278
|
+
'2005': VisualStudioVersion('2005',
|
279
|
+
'Visual Studio 2005',
|
280
|
+
solution_version='9.00',
|
281
|
+
project_version='8.00',
|
282
|
+
flat_sln=False,
|
283
|
+
uses_vcxproj=False,
|
284
|
+
path=path,
|
285
|
+
sdk_based=sdk_based),
|
286
|
+
'2005e': VisualStudioVersion('2005e',
|
287
|
+
'Visual Studio 2005',
|
288
|
+
solution_version='9.00',
|
289
|
+
project_version='8.00',
|
290
|
+
flat_sln=True,
|
291
|
+
uses_vcxproj=False,
|
292
|
+
path=path,
|
293
|
+
sdk_based=sdk_based),
|
294
|
+
}
|
295
|
+
return versions[str(name)]
|
296
|
+
|
297
|
+
|
298
|
+
def _ConvertToCygpath(path):
|
299
|
+
"""Convert to cygwin path if we are using cygwin."""
|
300
|
+
if sys.platform == 'cygwin':
|
301
|
+
p = subprocess.Popen(['cygpath', path], stdout=subprocess.PIPE)
|
302
|
+
path = p.communicate()[0].strip()
|
303
|
+
return path
|
304
|
+
|
305
|
+
|
306
|
+
def _DetectVisualStudioVersions(versions_to_check, force_express):
|
307
|
+
"""Collect the list of installed visual studio versions.
|
308
|
+
|
309
|
+
Returns:
|
310
|
+
A list of visual studio versions installed in descending order of
|
311
|
+
usage preference.
|
312
|
+
Base this on the registry and a quick check if devenv.exe exists.
|
313
|
+
Only versions 8-10 are considered.
|
314
|
+
Possibilities are:
|
315
|
+
2005(e) - Visual Studio 2005 (8)
|
316
|
+
2008(e) - Visual Studio 2008 (9)
|
317
|
+
2010(e) - Visual Studio 2010 (10)
|
318
|
+
2012(e) - Visual Studio 2012 (11)
|
319
|
+
2013(e) - Visual Studio 2013 (11)
|
320
|
+
Where (e) is e for express editions of MSVS and blank otherwise.
|
321
|
+
"""
|
322
|
+
version_to_year = {
|
323
|
+
'8.0': '2005',
|
324
|
+
'9.0': '2008',
|
325
|
+
'10.0': '2010',
|
326
|
+
'11.0': '2012',
|
327
|
+
'12.0': '2013',
|
328
|
+
}
|
329
|
+
versions = []
|
330
|
+
for version in versions_to_check:
|
331
|
+
# Old method of searching for which VS version is installed
|
332
|
+
# We don't use the 2010-encouraged-way because we also want to get the
|
333
|
+
# path to the binaries, which it doesn't offer.
|
334
|
+
keys = [r'HKLM\Software\Microsoft\VisualStudio\%s' % version,
|
335
|
+
r'HKLM\Software\Wow6432Node\Microsoft\VisualStudio\%s' % version,
|
336
|
+
r'HKLM\Software\Microsoft\VCExpress\%s' % version,
|
337
|
+
r'HKLM\Software\Wow6432Node\Microsoft\VCExpress\%s' % version]
|
338
|
+
for index in range(len(keys)):
|
339
|
+
path = _RegistryGetValue(keys[index], 'InstallDir')
|
340
|
+
if not path:
|
341
|
+
continue
|
342
|
+
path = _ConvertToCygpath(path)
|
343
|
+
# Check for full.
|
344
|
+
full_path = os.path.join(path, 'devenv.exe')
|
345
|
+
express_path = os.path.join(path, '*express.exe')
|
346
|
+
if not force_express and os.path.exists(full_path):
|
347
|
+
# Add this one.
|
348
|
+
versions.append(_CreateVersion(version_to_year[version],
|
349
|
+
os.path.join(path, '..', '..')))
|
350
|
+
# Check for express.
|
351
|
+
elif glob.glob(express_path):
|
352
|
+
# Add this one.
|
353
|
+
versions.append(_CreateVersion(version_to_year[version] + 'e',
|
354
|
+
os.path.join(path, '..', '..')))
|
355
|
+
|
356
|
+
# The old method above does not work when only SDK is installed.
|
357
|
+
keys = [r'HKLM\Software\Microsoft\VisualStudio\SxS\VC7',
|
358
|
+
r'HKLM\Software\Wow6432Node\Microsoft\VisualStudio\SxS\VC7']
|
359
|
+
for index in range(len(keys)):
|
360
|
+
path = _RegistryGetValue(keys[index], version)
|
361
|
+
if not path:
|
362
|
+
continue
|
363
|
+
path = _ConvertToCygpath(path)
|
364
|
+
versions.append(_CreateVersion(version_to_year[version] + 'e',
|
365
|
+
os.path.join(path, '..'), sdk_based=True))
|
366
|
+
|
367
|
+
return versions
|
368
|
+
|
369
|
+
|
370
|
+
def SelectVisualStudioVersion(version='auto'):
|
371
|
+
"""Select which version of Visual Studio projects to generate.
|
372
|
+
|
373
|
+
Arguments:
|
374
|
+
version: Hook to allow caller to force a particular version (vs auto).
|
375
|
+
Returns:
|
376
|
+
An object representing a visual studio project format version.
|
377
|
+
"""
|
378
|
+
# In auto mode, check environment variable for override.
|
379
|
+
if version == 'auto':
|
380
|
+
version = os.environ.get('GYP_MSVS_VERSION', 'auto')
|
381
|
+
version_map = {
|
382
|
+
'auto': ('10.0', '12.0', '9.0', '8.0', '11.0'),
|
383
|
+
'2005': ('8.0',),
|
384
|
+
'2005e': ('8.0',),
|
385
|
+
'2008': ('9.0',),
|
386
|
+
'2008e': ('9.0',),
|
387
|
+
'2010': ('10.0',),
|
388
|
+
'2010e': ('10.0',),
|
389
|
+
'2012': ('11.0',),
|
390
|
+
'2012e': ('11.0',),
|
391
|
+
'2013': ('12.0',),
|
392
|
+
'2013e': ('12.0',),
|
393
|
+
}
|
394
|
+
override_path = os.environ.get('GYP_MSVS_OVERRIDE_PATH')
|
395
|
+
if override_path:
|
396
|
+
msvs_version = os.environ.get('GYP_MSVS_VERSION')
|
397
|
+
if not msvs_version:
|
398
|
+
raise ValueError('GYP_MSVS_OVERRIDE_PATH requires GYP_MSVS_VERSION to be '
|
399
|
+
'set to a particular version (e.g. 2010e).')
|
400
|
+
return _CreateVersion(msvs_version, override_path, sdk_based=True)
|
401
|
+
version = str(version)
|
402
|
+
versions = _DetectVisualStudioVersions(version_map[version], 'e' in version)
|
403
|
+
if not versions:
|
404
|
+
if version == 'auto':
|
405
|
+
# Default to 2005 if we couldn't find anything
|
406
|
+
return _CreateVersion('2005', None)
|
407
|
+
else:
|
408
|
+
return _CreateVersion(version, None)
|
409
|
+
return versions[0]
|
@@ -0,0 +1,537 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
|
3
|
+
# Copyright (c) 2012 Google Inc. All rights reserved.
|
4
|
+
# Use of this source code is governed by a BSD-style license that can be
|
5
|
+
# found in the LICENSE file.
|
6
|
+
|
7
|
+
import copy
|
8
|
+
import gyp.input
|
9
|
+
import optparse
|
10
|
+
import os.path
|
11
|
+
import re
|
12
|
+
import shlex
|
13
|
+
import sys
|
14
|
+
import traceback
|
15
|
+
from gyp.common import GypError
|
16
|
+
|
17
|
+
# Default debug modes for GYP
|
18
|
+
debug = {}
|
19
|
+
|
20
|
+
# List of "official" debug modes, but you can use anything you like.
|
21
|
+
DEBUG_GENERAL = 'general'
|
22
|
+
DEBUG_VARIABLES = 'variables'
|
23
|
+
DEBUG_INCLUDES = 'includes'
|
24
|
+
|
25
|
+
|
26
|
+
def DebugOutput(mode, message, *args):
|
27
|
+
if 'all' in gyp.debug or mode in gyp.debug:
|
28
|
+
ctx = ('unknown', 0, 'unknown')
|
29
|
+
try:
|
30
|
+
f = traceback.extract_stack(limit=2)
|
31
|
+
if f:
|
32
|
+
ctx = f[0][:3]
|
33
|
+
except:
|
34
|
+
pass
|
35
|
+
if args:
|
36
|
+
message %= args
|
37
|
+
print '%s:%s:%d:%s %s' % (mode.upper(), os.path.basename(ctx[0]),
|
38
|
+
ctx[1], ctx[2], message)
|
39
|
+
|
40
|
+
def FindBuildFiles():
|
41
|
+
extension = '.gyp'
|
42
|
+
files = os.listdir(os.getcwd())
|
43
|
+
build_files = []
|
44
|
+
for file in files:
|
45
|
+
if file.endswith(extension):
|
46
|
+
build_files.append(file)
|
47
|
+
return build_files
|
48
|
+
|
49
|
+
|
50
|
+
def Load(build_files, format, default_variables={},
|
51
|
+
includes=[], depth='.', params=None, check=False,
|
52
|
+
circular_check=True):
|
53
|
+
"""
|
54
|
+
Loads one or more specified build files.
|
55
|
+
default_variables and includes will be copied before use.
|
56
|
+
Returns the generator for the specified format and the
|
57
|
+
data returned by loading the specified build files.
|
58
|
+
"""
|
59
|
+
if params is None:
|
60
|
+
params = {}
|
61
|
+
|
62
|
+
flavor = None
|
63
|
+
if '-' in format:
|
64
|
+
format, params['flavor'] = format.split('-', 1)
|
65
|
+
|
66
|
+
default_variables = copy.copy(default_variables)
|
67
|
+
|
68
|
+
# Default variables provided by this program and its modules should be
|
69
|
+
# named WITH_CAPITAL_LETTERS to provide a distinct "best practice" namespace,
|
70
|
+
# avoiding collisions with user and automatic variables.
|
71
|
+
default_variables['GENERATOR'] = format
|
72
|
+
|
73
|
+
# Format can be a custom python file, or by default the name of a module
|
74
|
+
# within gyp.generator.
|
75
|
+
if format.endswith('.py'):
|
76
|
+
generator_name = os.path.splitext(format)[0]
|
77
|
+
path, generator_name = os.path.split(generator_name)
|
78
|
+
|
79
|
+
# Make sure the path to the custom generator is in sys.path
|
80
|
+
# Don't worry about removing it once we are done. Keeping the path
|
81
|
+
# to each generator that is used in sys.path is likely harmless and
|
82
|
+
# arguably a good idea.
|
83
|
+
path = os.path.abspath(path)
|
84
|
+
if path not in sys.path:
|
85
|
+
sys.path.insert(0, path)
|
86
|
+
else:
|
87
|
+
generator_name = 'gyp.generator.' + format
|
88
|
+
|
89
|
+
# These parameters are passed in order (as opposed to by key)
|
90
|
+
# because ActivePython cannot handle key parameters to __import__.
|
91
|
+
generator = __import__(generator_name, globals(), locals(), generator_name)
|
92
|
+
for (key, val) in generator.generator_default_variables.items():
|
93
|
+
default_variables.setdefault(key, val)
|
94
|
+
|
95
|
+
# Give the generator the opportunity to set additional variables based on
|
96
|
+
# the params it will receive in the output phase.
|
97
|
+
if getattr(generator, 'CalculateVariables', None):
|
98
|
+
generator.CalculateVariables(default_variables, params)
|
99
|
+
|
100
|
+
# Give the generator the opportunity to set generator_input_info based on
|
101
|
+
# the params it will receive in the output phase.
|
102
|
+
if getattr(generator, 'CalculateGeneratorInputInfo', None):
|
103
|
+
generator.CalculateGeneratorInputInfo(params)
|
104
|
+
|
105
|
+
# Fetch the generator specific info that gets fed to input, we use getattr
|
106
|
+
# so we can default things and the generators only have to provide what
|
107
|
+
# they need.
|
108
|
+
generator_input_info = {
|
109
|
+
'non_configuration_keys':
|
110
|
+
getattr(generator, 'generator_additional_non_configuration_keys', []),
|
111
|
+
'path_sections':
|
112
|
+
getattr(generator, 'generator_additional_path_sections', []),
|
113
|
+
'extra_sources_for_rules':
|
114
|
+
getattr(generator, 'generator_extra_sources_for_rules', []),
|
115
|
+
'generator_supports_multiple_toolsets':
|
116
|
+
getattr(generator, 'generator_supports_multiple_toolsets', False),
|
117
|
+
'generator_wants_static_library_dependencies_adjusted':
|
118
|
+
getattr(generator,
|
119
|
+
'generator_wants_static_library_dependencies_adjusted', True),
|
120
|
+
'generator_wants_sorted_dependencies':
|
121
|
+
getattr(generator, 'generator_wants_sorted_dependencies', False),
|
122
|
+
'generator_filelist_paths':
|
123
|
+
getattr(generator, 'generator_filelist_paths', None),
|
124
|
+
}
|
125
|
+
|
126
|
+
# Process the input specific to this generator.
|
127
|
+
result = gyp.input.Load(build_files, default_variables, includes[:],
|
128
|
+
depth, generator_input_info, check, circular_check,
|
129
|
+
params['parallel'], params['root_targets'])
|
130
|
+
return [generator] + result
|
131
|
+
|
132
|
+
def NameValueListToDict(name_value_list):
|
133
|
+
"""
|
134
|
+
Takes an array of strings of the form 'NAME=VALUE' and creates a dictionary
|
135
|
+
of the pairs. If a string is simply NAME, then the value in the dictionary
|
136
|
+
is set to True. If VALUE can be converted to an integer, it is.
|
137
|
+
"""
|
138
|
+
result = { }
|
139
|
+
for item in name_value_list:
|
140
|
+
tokens = item.split('=', 1)
|
141
|
+
if len(tokens) == 2:
|
142
|
+
# If we can make it an int, use that, otherwise, use the string.
|
143
|
+
try:
|
144
|
+
token_value = int(tokens[1])
|
145
|
+
except ValueError:
|
146
|
+
token_value = tokens[1]
|
147
|
+
# Set the variable to the supplied value.
|
148
|
+
result[tokens[0]] = token_value
|
149
|
+
else:
|
150
|
+
# No value supplied, treat it as a boolean and set it.
|
151
|
+
result[tokens[0]] = True
|
152
|
+
return result
|
153
|
+
|
154
|
+
def ShlexEnv(env_name):
|
155
|
+
flags = os.environ.get(env_name, [])
|
156
|
+
if flags:
|
157
|
+
flags = shlex.split(flags)
|
158
|
+
return flags
|
159
|
+
|
160
|
+
def FormatOpt(opt, value):
|
161
|
+
if opt.startswith('--'):
|
162
|
+
return '%s=%s' % (opt, value)
|
163
|
+
return opt + value
|
164
|
+
|
165
|
+
def RegenerateAppendFlag(flag, values, predicate, env_name, options):
|
166
|
+
"""Regenerate a list of command line flags, for an option of action='append'.
|
167
|
+
|
168
|
+
The |env_name|, if given, is checked in the environment and used to generate
|
169
|
+
an initial list of options, then the options that were specified on the
|
170
|
+
command line (given in |values|) are appended. This matches the handling of
|
171
|
+
environment variables and command line flags where command line flags override
|
172
|
+
the environment, while not requiring the environment to be set when the flags
|
173
|
+
are used again.
|
174
|
+
"""
|
175
|
+
flags = []
|
176
|
+
if options.use_environment and env_name:
|
177
|
+
for flag_value in ShlexEnv(env_name):
|
178
|
+
value = FormatOpt(flag, predicate(flag_value))
|
179
|
+
if value in flags:
|
180
|
+
flags.remove(value)
|
181
|
+
flags.append(value)
|
182
|
+
if values:
|
183
|
+
for flag_value in values:
|
184
|
+
flags.append(FormatOpt(flag, predicate(flag_value)))
|
185
|
+
return flags
|
186
|
+
|
187
|
+
def RegenerateFlags(options):
|
188
|
+
"""Given a parsed options object, and taking the environment variables into
|
189
|
+
account, returns a list of flags that should regenerate an equivalent options
|
190
|
+
object (even in the absence of the environment variables.)
|
191
|
+
|
192
|
+
Any path options will be normalized relative to depth.
|
193
|
+
|
194
|
+
The format flag is not included, as it is assumed the calling generator will
|
195
|
+
set that as appropriate.
|
196
|
+
"""
|
197
|
+
def FixPath(path):
|
198
|
+
path = gyp.common.FixIfRelativePath(path, options.depth)
|
199
|
+
if not path:
|
200
|
+
return os.path.curdir
|
201
|
+
return path
|
202
|
+
|
203
|
+
def Noop(value):
|
204
|
+
return value
|
205
|
+
|
206
|
+
# We always want to ignore the environment when regenerating, to avoid
|
207
|
+
# duplicate or changed flags in the environment at the time of regeneration.
|
208
|
+
flags = ['--ignore-environment']
|
209
|
+
for name, metadata in options._regeneration_metadata.iteritems():
|
210
|
+
opt = metadata['opt']
|
211
|
+
value = getattr(options, name)
|
212
|
+
value_predicate = metadata['type'] == 'path' and FixPath or Noop
|
213
|
+
action = metadata['action']
|
214
|
+
env_name = metadata['env_name']
|
215
|
+
if action == 'append':
|
216
|
+
flags.extend(RegenerateAppendFlag(opt, value, value_predicate,
|
217
|
+
env_name, options))
|
218
|
+
elif action in ('store', None): # None is a synonym for 'store'.
|
219
|
+
if value:
|
220
|
+
flags.append(FormatOpt(opt, value_predicate(value)))
|
221
|
+
elif options.use_environment and env_name and os.environ.get(env_name):
|
222
|
+
flags.append(FormatOpt(opt, value_predicate(os.environ.get(env_name))))
|
223
|
+
elif action in ('store_true', 'store_false'):
|
224
|
+
if ((action == 'store_true' and value) or
|
225
|
+
(action == 'store_false' and not value)):
|
226
|
+
flags.append(opt)
|
227
|
+
elif options.use_environment and env_name:
|
228
|
+
print >>sys.stderr, ('Warning: environment regeneration unimplemented '
|
229
|
+
'for %s flag %r env_name %r' % (action, opt,
|
230
|
+
env_name))
|
231
|
+
else:
|
232
|
+
print >>sys.stderr, ('Warning: regeneration unimplemented for action %r '
|
233
|
+
'flag %r' % (action, opt))
|
234
|
+
|
235
|
+
return flags
|
236
|
+
|
237
|
+
class RegeneratableOptionParser(optparse.OptionParser):
|
238
|
+
def __init__(self):
|
239
|
+
self.__regeneratable_options = {}
|
240
|
+
optparse.OptionParser.__init__(self)
|
241
|
+
|
242
|
+
def add_option(self, *args, **kw):
|
243
|
+
"""Add an option to the parser.
|
244
|
+
|
245
|
+
This accepts the same arguments as OptionParser.add_option, plus the
|
246
|
+
following:
|
247
|
+
regenerate: can be set to False to prevent this option from being included
|
248
|
+
in regeneration.
|
249
|
+
env_name: name of environment variable that additional values for this
|
250
|
+
option come from.
|
251
|
+
type: adds type='path', to tell the regenerator that the values of
|
252
|
+
this option need to be made relative to options.depth
|
253
|
+
"""
|
254
|
+
env_name = kw.pop('env_name', None)
|
255
|
+
if 'dest' in kw and kw.pop('regenerate', True):
|
256
|
+
dest = kw['dest']
|
257
|
+
|
258
|
+
# The path type is needed for regenerating, for optparse we can just treat
|
259
|
+
# it as a string.
|
260
|
+
type = kw.get('type')
|
261
|
+
if type == 'path':
|
262
|
+
kw['type'] = 'string'
|
263
|
+
|
264
|
+
self.__regeneratable_options[dest] = {
|
265
|
+
'action': kw.get('action'),
|
266
|
+
'type': type,
|
267
|
+
'env_name': env_name,
|
268
|
+
'opt': args[0],
|
269
|
+
}
|
270
|
+
|
271
|
+
optparse.OptionParser.add_option(self, *args, **kw)
|
272
|
+
|
273
|
+
def parse_args(self, *args):
|
274
|
+
values, args = optparse.OptionParser.parse_args(self, *args)
|
275
|
+
values._regeneration_metadata = self.__regeneratable_options
|
276
|
+
return values, args
|
277
|
+
|
278
|
+
def gyp_main(args):
|
279
|
+
my_name = os.path.basename(sys.argv[0])
|
280
|
+
|
281
|
+
parser = RegeneratableOptionParser()
|
282
|
+
usage = 'usage: %s [options ...] [build_file ...]'
|
283
|
+
parser.set_usage(usage.replace('%s', '%prog'))
|
284
|
+
parser.add_option('--build', dest='configs', action='append',
|
285
|
+
help='configuration for build after project generation')
|
286
|
+
parser.add_option('--check', dest='check', action='store_true',
|
287
|
+
help='check format of gyp files')
|
288
|
+
parser.add_option('--config-dir', dest='config_dir', action='store',
|
289
|
+
env_name='GYP_CONFIG_DIR', default=None,
|
290
|
+
help='The location for configuration files like '
|
291
|
+
'include.gypi.')
|
292
|
+
parser.add_option('-d', '--debug', dest='debug', metavar='DEBUGMODE',
|
293
|
+
action='append', default=[], help='turn on a debugging '
|
294
|
+
'mode for debugging GYP. Supported modes are "variables", '
|
295
|
+
'"includes" and "general" or "all" for all of them.')
|
296
|
+
parser.add_option('-D', dest='defines', action='append', metavar='VAR=VAL',
|
297
|
+
env_name='GYP_DEFINES',
|
298
|
+
help='sets variable VAR to value VAL')
|
299
|
+
parser.add_option('--depth', dest='depth', metavar='PATH', type='path',
|
300
|
+
help='set DEPTH gyp variable to a relative path to PATH')
|
301
|
+
parser.add_option('-f', '--format', dest='formats', action='append',
|
302
|
+
env_name='GYP_GENERATORS', regenerate=False,
|
303
|
+
help='output formats to generate')
|
304
|
+
parser.add_option('-G', dest='generator_flags', action='append', default=[],
|
305
|
+
metavar='FLAG=VAL', env_name='GYP_GENERATOR_FLAGS',
|
306
|
+
help='sets generator flag FLAG to VAL')
|
307
|
+
parser.add_option('--generator-output', dest='generator_output',
|
308
|
+
action='store', default=None, metavar='DIR', type='path',
|
309
|
+
env_name='GYP_GENERATOR_OUTPUT',
|
310
|
+
help='puts generated build files under DIR')
|
311
|
+
parser.add_option('--ignore-environment', dest='use_environment',
|
312
|
+
action='store_false', default=True, regenerate=False,
|
313
|
+
help='do not read options from environment variables')
|
314
|
+
parser.add_option('-I', '--include', dest='includes', action='append',
|
315
|
+
metavar='INCLUDE', type='path',
|
316
|
+
help='files to include in all loaded .gyp files')
|
317
|
+
# --no-circular-check disables the check for circular relationships between
|
318
|
+
# .gyp files. These relationships should not exist, but they've only been
|
319
|
+
# observed to be harmful with the Xcode generator. Chromium's .gyp files
|
320
|
+
# currently have some circular relationships on non-Mac platforms, so this
|
321
|
+
# option allows the strict behavior to be used on Macs and the lenient
|
322
|
+
# behavior to be used elsewhere.
|
323
|
+
# TODO(mark): Remove this option when http://crbug.com/35878 is fixed.
|
324
|
+
parser.add_option('--no-circular-check', dest='circular_check',
|
325
|
+
action='store_false', default=True, regenerate=False,
|
326
|
+
help="don't check for circular relationships between files")
|
327
|
+
parser.add_option('--no-parallel', action='store_true', default=False,
|
328
|
+
help='Disable multiprocessing')
|
329
|
+
parser.add_option('-S', '--suffix', dest='suffix', default='',
|
330
|
+
help='suffix to add to generated files')
|
331
|
+
parser.add_option('--toplevel-dir', dest='toplevel_dir', action='store',
|
332
|
+
default=None, metavar='DIR', type='path',
|
333
|
+
help='directory to use as the root of the source tree')
|
334
|
+
parser.add_option('-R', '--root-target', dest='root_targets',
|
335
|
+
action='append', metavar='TARGET',
|
336
|
+
help='include only TARGET and its deep dependencies')
|
337
|
+
|
338
|
+
options, build_files_arg = parser.parse_args(args)
|
339
|
+
build_files = build_files_arg
|
340
|
+
|
341
|
+
# Set up the configuration directory (defaults to ~/.gyp)
|
342
|
+
if not options.config_dir:
|
343
|
+
home = None
|
344
|
+
home_dot_gyp = None
|
345
|
+
if options.use_environment:
|
346
|
+
home_dot_gyp = os.environ.get('GYP_CONFIG_DIR', None)
|
347
|
+
if home_dot_gyp:
|
348
|
+
home_dot_gyp = os.path.expanduser(home_dot_gyp)
|
349
|
+
|
350
|
+
if not home_dot_gyp:
|
351
|
+
home_vars = ['HOME']
|
352
|
+
if sys.platform in ('cygwin', 'win32'):
|
353
|
+
home_vars.append('USERPROFILE')
|
354
|
+
for home_var in home_vars:
|
355
|
+
home = os.getenv(home_var)
|
356
|
+
if home != None:
|
357
|
+
home_dot_gyp = os.path.join(home, '.gyp')
|
358
|
+
if not os.path.exists(home_dot_gyp):
|
359
|
+
home_dot_gyp = None
|
360
|
+
else:
|
361
|
+
break
|
362
|
+
else:
|
363
|
+
home_dot_gyp = os.path.expanduser(options.config_dir)
|
364
|
+
|
365
|
+
if home_dot_gyp and not os.path.exists(home_dot_gyp):
|
366
|
+
home_dot_gyp = None
|
367
|
+
|
368
|
+
if not options.formats:
|
369
|
+
# If no format was given on the command line, then check the env variable.
|
370
|
+
generate_formats = []
|
371
|
+
if options.use_environment:
|
372
|
+
generate_formats = os.environ.get('GYP_GENERATORS', [])
|
373
|
+
if generate_formats:
|
374
|
+
generate_formats = re.split('[\s,]', generate_formats)
|
375
|
+
if generate_formats:
|
376
|
+
options.formats = generate_formats
|
377
|
+
else:
|
378
|
+
# Nothing in the variable, default based on platform.
|
379
|
+
if sys.platform == 'darwin':
|
380
|
+
options.formats = ['xcode']
|
381
|
+
elif sys.platform in ('win32', 'cygwin'):
|
382
|
+
options.formats = ['msvs']
|
383
|
+
else:
|
384
|
+
options.formats = ['make']
|
385
|
+
|
386
|
+
if not options.generator_output and options.use_environment:
|
387
|
+
g_o = os.environ.get('GYP_GENERATOR_OUTPUT')
|
388
|
+
if g_o:
|
389
|
+
options.generator_output = g_o
|
390
|
+
|
391
|
+
options.parallel = not options.no_parallel
|
392
|
+
|
393
|
+
for mode in options.debug:
|
394
|
+
gyp.debug[mode] = 1
|
395
|
+
|
396
|
+
# Do an extra check to avoid work when we're not debugging.
|
397
|
+
if DEBUG_GENERAL in gyp.debug:
|
398
|
+
DebugOutput(DEBUG_GENERAL, 'running with these options:')
|
399
|
+
for option, value in sorted(options.__dict__.items()):
|
400
|
+
if option[0] == '_':
|
401
|
+
continue
|
402
|
+
if isinstance(value, basestring):
|
403
|
+
DebugOutput(DEBUG_GENERAL, " %s: '%s'", option, value)
|
404
|
+
else:
|
405
|
+
DebugOutput(DEBUG_GENERAL, " %s: %s", option, value)
|
406
|
+
|
407
|
+
if not build_files:
|
408
|
+
build_files = FindBuildFiles()
|
409
|
+
if not build_files:
|
410
|
+
raise GypError((usage + '\n\n%s: error: no build_file') %
|
411
|
+
(my_name, my_name))
|
412
|
+
|
413
|
+
# TODO(mark): Chromium-specific hack!
|
414
|
+
# For Chromium, the gyp "depth" variable should always be a relative path
|
415
|
+
# to Chromium's top-level "src" directory. If no depth variable was set
|
416
|
+
# on the command line, try to find a "src" directory by looking at the
|
417
|
+
# absolute path to each build file's directory. The first "src" component
|
418
|
+
# found will be treated as though it were the path used for --depth.
|
419
|
+
if not options.depth:
|
420
|
+
for build_file in build_files:
|
421
|
+
build_file_dir = os.path.abspath(os.path.dirname(build_file))
|
422
|
+
build_file_dir_components = build_file_dir.split(os.path.sep)
|
423
|
+
components_len = len(build_file_dir_components)
|
424
|
+
for index in xrange(components_len - 1, -1, -1):
|
425
|
+
if build_file_dir_components[index] == 'src':
|
426
|
+
options.depth = os.path.sep.join(build_file_dir_components)
|
427
|
+
break
|
428
|
+
del build_file_dir_components[index]
|
429
|
+
|
430
|
+
# If the inner loop found something, break without advancing to another
|
431
|
+
# build file.
|
432
|
+
if options.depth:
|
433
|
+
break
|
434
|
+
|
435
|
+
if not options.depth:
|
436
|
+
raise GypError('Could not automatically locate src directory. This is'
|
437
|
+
'a temporary Chromium feature that will be removed. Use'
|
438
|
+
'--depth as a workaround.')
|
439
|
+
|
440
|
+
# If toplevel-dir is not set, we assume that depth is the root of our source
|
441
|
+
# tree.
|
442
|
+
if not options.toplevel_dir:
|
443
|
+
options.toplevel_dir = options.depth
|
444
|
+
|
445
|
+
# -D on the command line sets variable defaults - D isn't just for define,
|
446
|
+
# it's for default. Perhaps there should be a way to force (-F?) a
|
447
|
+
# variable's value so that it can't be overridden by anything else.
|
448
|
+
cmdline_default_variables = {}
|
449
|
+
defines = []
|
450
|
+
if options.use_environment:
|
451
|
+
defines += ShlexEnv('GYP_DEFINES')
|
452
|
+
if options.defines:
|
453
|
+
defines += options.defines
|
454
|
+
cmdline_default_variables = NameValueListToDict(defines)
|
455
|
+
if DEBUG_GENERAL in gyp.debug:
|
456
|
+
DebugOutput(DEBUG_GENERAL,
|
457
|
+
"cmdline_default_variables: %s", cmdline_default_variables)
|
458
|
+
|
459
|
+
# Set up includes.
|
460
|
+
includes = []
|
461
|
+
|
462
|
+
# If ~/.gyp/include.gypi exists, it'll be forcibly included into every
|
463
|
+
# .gyp file that's loaded, before anything else is included.
|
464
|
+
if home_dot_gyp != None:
|
465
|
+
default_include = os.path.join(home_dot_gyp, 'include.gypi')
|
466
|
+
if os.path.exists(default_include):
|
467
|
+
print 'Using overrides found in ' + default_include
|
468
|
+
includes.append(default_include)
|
469
|
+
|
470
|
+
# Command-line --include files come after the default include.
|
471
|
+
if options.includes:
|
472
|
+
includes.extend(options.includes)
|
473
|
+
|
474
|
+
# Generator flags should be prefixed with the target generator since they
|
475
|
+
# are global across all generator runs.
|
476
|
+
gen_flags = []
|
477
|
+
if options.use_environment:
|
478
|
+
gen_flags += ShlexEnv('GYP_GENERATOR_FLAGS')
|
479
|
+
if options.generator_flags:
|
480
|
+
gen_flags += options.generator_flags
|
481
|
+
generator_flags = NameValueListToDict(gen_flags)
|
482
|
+
if DEBUG_GENERAL in gyp.debug.keys():
|
483
|
+
DebugOutput(DEBUG_GENERAL, "generator_flags: %s", generator_flags)
|
484
|
+
|
485
|
+
# Generate all requested formats (use a set in case we got one format request
|
486
|
+
# twice)
|
487
|
+
for format in set(options.formats):
|
488
|
+
params = {'options': options,
|
489
|
+
'build_files': build_files,
|
490
|
+
'generator_flags': generator_flags,
|
491
|
+
'cwd': os.getcwd(),
|
492
|
+
'build_files_arg': build_files_arg,
|
493
|
+
'gyp_binary': sys.argv[0],
|
494
|
+
'home_dot_gyp': home_dot_gyp,
|
495
|
+
'parallel': options.parallel,
|
496
|
+
'root_targets': options.root_targets}
|
497
|
+
|
498
|
+
# Start with the default variables from the command line.
|
499
|
+
[generator, flat_list, targets, data] = Load(build_files, format,
|
500
|
+
cmdline_default_variables,
|
501
|
+
includes, options.depth,
|
502
|
+
params, options.check,
|
503
|
+
options.circular_check)
|
504
|
+
|
505
|
+
# TODO(mark): Pass |data| for now because the generator needs a list of
|
506
|
+
# build files that came in. In the future, maybe it should just accept
|
507
|
+
# a list, and not the whole data dict.
|
508
|
+
# NOTE: flat_list is the flattened dependency graph specifying the order
|
509
|
+
# that targets may be built. Build systems that operate serially or that
|
510
|
+
# need to have dependencies defined before dependents reference them should
|
511
|
+
# generate targets in the order specified in flat_list.
|
512
|
+
generator.GenerateOutput(flat_list, targets, data, params)
|
513
|
+
|
514
|
+
if options.configs:
|
515
|
+
valid_configs = targets[flat_list[0]]['configurations'].keys()
|
516
|
+
for conf in options.configs:
|
517
|
+
if conf not in valid_configs:
|
518
|
+
raise GypError('Invalid config specified via --build: %s' % conf)
|
519
|
+
generator.PerformBuild(data, options.configs, params)
|
520
|
+
|
521
|
+
# Done
|
522
|
+
return 0
|
523
|
+
|
524
|
+
|
525
|
+
def main(args):
|
526
|
+
try:
|
527
|
+
return gyp_main(args)
|
528
|
+
except GypError, e:
|
529
|
+
sys.stderr.write("gyp: %s\n" % e)
|
530
|
+
return 1
|
531
|
+
|
532
|
+
# NOTE: setuptools generated console_scripts calls function with no arguments
|
533
|
+
def script_main():
|
534
|
+
return main(sys.argv[1:])
|
535
|
+
|
536
|
+
if __name__ == '__main__':
|
537
|
+
sys.exit(script_main())
|