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,340 @@
|
|
1
|
+
# Copyright (c) 2012 Google Inc. All rights reserved.
|
2
|
+
# Use of this source code is governed by a BSD-style license that can be
|
3
|
+
# found in the LICENSE file.
|
4
|
+
|
5
|
+
"""New implementation of Visual Studio project generation."""
|
6
|
+
|
7
|
+
import os
|
8
|
+
import random
|
9
|
+
|
10
|
+
import gyp.common
|
11
|
+
|
12
|
+
# hashlib is supplied as of Python 2.5 as the replacement interface for md5
|
13
|
+
# and other secure hashes. In 2.6, md5 is deprecated. Import hashlib if
|
14
|
+
# available, avoiding a deprecation warning under 2.6. Import md5 otherwise,
|
15
|
+
# preserving 2.4 compatibility.
|
16
|
+
try:
|
17
|
+
import hashlib
|
18
|
+
_new_md5 = hashlib.md5
|
19
|
+
except ImportError:
|
20
|
+
import md5
|
21
|
+
_new_md5 = md5.new
|
22
|
+
|
23
|
+
|
24
|
+
# Initialize random number generator
|
25
|
+
random.seed()
|
26
|
+
|
27
|
+
# GUIDs for project types
|
28
|
+
ENTRY_TYPE_GUIDS = {
|
29
|
+
'project': '{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}',
|
30
|
+
'folder': '{2150E333-8FDC-42A3-9474-1A3956D46DE8}',
|
31
|
+
}
|
32
|
+
|
33
|
+
#------------------------------------------------------------------------------
|
34
|
+
# Helper functions
|
35
|
+
|
36
|
+
|
37
|
+
def MakeGuid(name, seed='msvs_new'):
|
38
|
+
"""Returns a GUID for the specified target name.
|
39
|
+
|
40
|
+
Args:
|
41
|
+
name: Target name.
|
42
|
+
seed: Seed for MD5 hash.
|
43
|
+
Returns:
|
44
|
+
A GUID-line string calculated from the name and seed.
|
45
|
+
|
46
|
+
This generates something which looks like a GUID, but depends only on the
|
47
|
+
name and seed. This means the same name/seed will always generate the same
|
48
|
+
GUID, so that projects and solutions which refer to each other can explicitly
|
49
|
+
determine the GUID to refer to explicitly. It also means that the GUID will
|
50
|
+
not change when the project for a target is rebuilt.
|
51
|
+
"""
|
52
|
+
# Calculate a MD5 signature for the seed and name.
|
53
|
+
d = _new_md5(str(seed) + str(name)).hexdigest().upper()
|
54
|
+
# Convert most of the signature to GUID form (discard the rest)
|
55
|
+
guid = ('{' + d[:8] + '-' + d[8:12] + '-' + d[12:16] + '-' + d[16:20]
|
56
|
+
+ '-' + d[20:32] + '}')
|
57
|
+
return guid
|
58
|
+
|
59
|
+
#------------------------------------------------------------------------------
|
60
|
+
|
61
|
+
|
62
|
+
class MSVSSolutionEntry(object):
|
63
|
+
def __cmp__(self, other):
|
64
|
+
# Sort by name then guid (so things are in order on vs2008).
|
65
|
+
return cmp((self.name, self.get_guid()), (other.name, other.get_guid()))
|
66
|
+
|
67
|
+
|
68
|
+
class MSVSFolder(MSVSSolutionEntry):
|
69
|
+
"""Folder in a Visual Studio project or solution."""
|
70
|
+
|
71
|
+
def __init__(self, path, name = None, entries = None,
|
72
|
+
guid = None, items = None):
|
73
|
+
"""Initializes the folder.
|
74
|
+
|
75
|
+
Args:
|
76
|
+
path: Full path to the folder.
|
77
|
+
name: Name of the folder.
|
78
|
+
entries: List of folder entries to nest inside this folder. May contain
|
79
|
+
Folder or Project objects. May be None, if the folder is empty.
|
80
|
+
guid: GUID to use for folder, if not None.
|
81
|
+
items: List of solution items to include in the folder project. May be
|
82
|
+
None, if the folder does not directly contain items.
|
83
|
+
"""
|
84
|
+
if name:
|
85
|
+
self.name = name
|
86
|
+
else:
|
87
|
+
# Use last layer.
|
88
|
+
self.name = os.path.basename(path)
|
89
|
+
|
90
|
+
self.path = path
|
91
|
+
self.guid = guid
|
92
|
+
|
93
|
+
# Copy passed lists (or set to empty lists)
|
94
|
+
self.entries = sorted(list(entries or []))
|
95
|
+
self.items = list(items or [])
|
96
|
+
|
97
|
+
self.entry_type_guid = ENTRY_TYPE_GUIDS['folder']
|
98
|
+
|
99
|
+
def get_guid(self):
|
100
|
+
if self.guid is None:
|
101
|
+
# Use consistent guids for folders (so things don't regenerate).
|
102
|
+
self.guid = MakeGuid(self.path, seed='msvs_folder')
|
103
|
+
return self.guid
|
104
|
+
|
105
|
+
|
106
|
+
#------------------------------------------------------------------------------
|
107
|
+
|
108
|
+
|
109
|
+
class MSVSProject(MSVSSolutionEntry):
|
110
|
+
"""Visual Studio project."""
|
111
|
+
|
112
|
+
def __init__(self, path, name = None, dependencies = None, guid = None,
|
113
|
+
spec = None, build_file = None, config_platform_overrides = None,
|
114
|
+
fixpath_prefix = None):
|
115
|
+
"""Initializes the project.
|
116
|
+
|
117
|
+
Args:
|
118
|
+
path: Absolute path to the project file.
|
119
|
+
name: Name of project. If None, the name will be the same as the base
|
120
|
+
name of the project file.
|
121
|
+
dependencies: List of other Project objects this project is dependent
|
122
|
+
upon, if not None.
|
123
|
+
guid: GUID to use for project, if not None.
|
124
|
+
spec: Dictionary specifying how to build this project.
|
125
|
+
build_file: Filename of the .gyp file that the vcproj file comes from.
|
126
|
+
config_platform_overrides: optional dict of configuration platforms to
|
127
|
+
used in place of the default for this target.
|
128
|
+
fixpath_prefix: the path used to adjust the behavior of _fixpath
|
129
|
+
"""
|
130
|
+
self.path = path
|
131
|
+
self.guid = guid
|
132
|
+
self.spec = spec
|
133
|
+
self.build_file = build_file
|
134
|
+
# Use project filename if name not specified
|
135
|
+
self.name = name or os.path.splitext(os.path.basename(path))[0]
|
136
|
+
|
137
|
+
# Copy passed lists (or set to empty lists)
|
138
|
+
self.dependencies = list(dependencies or [])
|
139
|
+
|
140
|
+
self.entry_type_guid = ENTRY_TYPE_GUIDS['project']
|
141
|
+
|
142
|
+
if config_platform_overrides:
|
143
|
+
self.config_platform_overrides = config_platform_overrides
|
144
|
+
else:
|
145
|
+
self.config_platform_overrides = {}
|
146
|
+
self.fixpath_prefix = fixpath_prefix
|
147
|
+
self.msbuild_toolset = None
|
148
|
+
|
149
|
+
def set_dependencies(self, dependencies):
|
150
|
+
self.dependencies = list(dependencies or [])
|
151
|
+
|
152
|
+
def get_guid(self):
|
153
|
+
if self.guid is None:
|
154
|
+
# Set GUID from path
|
155
|
+
# TODO(rspangler): This is fragile.
|
156
|
+
# 1. We can't just use the project filename sans path, since there could
|
157
|
+
# be multiple projects with the same base name (for example,
|
158
|
+
# foo/unittest.vcproj and bar/unittest.vcproj).
|
159
|
+
# 2. The path needs to be relative to $SOURCE_ROOT, so that the project
|
160
|
+
# GUID is the same whether it's included from base/base.sln or
|
161
|
+
# foo/bar/baz/baz.sln.
|
162
|
+
# 3. The GUID needs to be the same each time this builder is invoked, so
|
163
|
+
# that we don't need to rebuild the solution when the project changes.
|
164
|
+
# 4. We should be able to handle pre-built project files by reading the
|
165
|
+
# GUID from the files.
|
166
|
+
self.guid = MakeGuid(self.name)
|
167
|
+
return self.guid
|
168
|
+
|
169
|
+
def set_msbuild_toolset(self, msbuild_toolset):
|
170
|
+
self.msbuild_toolset = msbuild_toolset
|
171
|
+
|
172
|
+
#------------------------------------------------------------------------------
|
173
|
+
|
174
|
+
|
175
|
+
class MSVSSolution:
|
176
|
+
"""Visual Studio solution."""
|
177
|
+
|
178
|
+
def __init__(self, path, version, entries=None, variants=None,
|
179
|
+
websiteProperties=True):
|
180
|
+
"""Initializes the solution.
|
181
|
+
|
182
|
+
Args:
|
183
|
+
path: Path to solution file.
|
184
|
+
version: Format version to emit.
|
185
|
+
entries: List of entries in solution. May contain Folder or Project
|
186
|
+
objects. May be None, if the folder is empty.
|
187
|
+
variants: List of build variant strings. If none, a default list will
|
188
|
+
be used.
|
189
|
+
websiteProperties: Flag to decide if the website properties section
|
190
|
+
is generated.
|
191
|
+
"""
|
192
|
+
self.path = path
|
193
|
+
self.websiteProperties = websiteProperties
|
194
|
+
self.version = version
|
195
|
+
|
196
|
+
# Copy passed lists (or set to empty lists)
|
197
|
+
self.entries = list(entries or [])
|
198
|
+
|
199
|
+
if variants:
|
200
|
+
# Copy passed list
|
201
|
+
self.variants = variants[:]
|
202
|
+
else:
|
203
|
+
# Use default
|
204
|
+
self.variants = ['Debug|Win32', 'Release|Win32']
|
205
|
+
# TODO(rspangler): Need to be able to handle a mapping of solution config
|
206
|
+
# to project config. Should we be able to handle variants being a dict,
|
207
|
+
# or add a separate variant_map variable? If it's a dict, we can't
|
208
|
+
# guarantee the order of variants since dict keys aren't ordered.
|
209
|
+
|
210
|
+
|
211
|
+
# TODO(rspangler): Automatically write to disk for now; should delay until
|
212
|
+
# node-evaluation time.
|
213
|
+
self.Write()
|
214
|
+
|
215
|
+
|
216
|
+
def Write(self, writer=gyp.common.WriteOnDiff):
|
217
|
+
"""Writes the solution file to disk.
|
218
|
+
|
219
|
+
Raises:
|
220
|
+
IndexError: An entry appears multiple times.
|
221
|
+
"""
|
222
|
+
# Walk the entry tree and collect all the folders and projects.
|
223
|
+
all_entries = set()
|
224
|
+
entries_to_check = self.entries[:]
|
225
|
+
while entries_to_check:
|
226
|
+
e = entries_to_check.pop(0)
|
227
|
+
|
228
|
+
# If this entry has been visited, nothing to do.
|
229
|
+
if e in all_entries:
|
230
|
+
continue
|
231
|
+
|
232
|
+
all_entries.add(e)
|
233
|
+
|
234
|
+
# If this is a folder, check its entries too.
|
235
|
+
if isinstance(e, MSVSFolder):
|
236
|
+
entries_to_check += e.entries
|
237
|
+
|
238
|
+
all_entries = sorted(all_entries)
|
239
|
+
|
240
|
+
# Open file and print header
|
241
|
+
f = writer(self.path)
|
242
|
+
f.write('Microsoft Visual Studio Solution File, '
|
243
|
+
'Format Version %s\r\n' % self.version.SolutionVersion())
|
244
|
+
f.write('# %s\r\n' % self.version.Description())
|
245
|
+
|
246
|
+
# Project entries
|
247
|
+
sln_root = os.path.split(self.path)[0]
|
248
|
+
for e in all_entries:
|
249
|
+
relative_path = gyp.common.RelativePath(e.path, sln_root)
|
250
|
+
# msbuild does not accept an empty folder_name.
|
251
|
+
# use '.' in case relative_path is empty.
|
252
|
+
folder_name = relative_path.replace('/', '\\') or '.'
|
253
|
+
f.write('Project("%s") = "%s", "%s", "%s"\r\n' % (
|
254
|
+
e.entry_type_guid, # Entry type GUID
|
255
|
+
e.name, # Folder name
|
256
|
+
folder_name, # Folder name (again)
|
257
|
+
e.get_guid(), # Entry GUID
|
258
|
+
))
|
259
|
+
|
260
|
+
# TODO(rspangler): Need a way to configure this stuff
|
261
|
+
if self.websiteProperties:
|
262
|
+
f.write('\tProjectSection(WebsiteProperties) = preProject\r\n'
|
263
|
+
'\t\tDebug.AspNetCompiler.Debug = "True"\r\n'
|
264
|
+
'\t\tRelease.AspNetCompiler.Debug = "False"\r\n'
|
265
|
+
'\tEndProjectSection\r\n')
|
266
|
+
|
267
|
+
if isinstance(e, MSVSFolder):
|
268
|
+
if e.items:
|
269
|
+
f.write('\tProjectSection(SolutionItems) = preProject\r\n')
|
270
|
+
for i in e.items:
|
271
|
+
f.write('\t\t%s = %s\r\n' % (i, i))
|
272
|
+
f.write('\tEndProjectSection\r\n')
|
273
|
+
|
274
|
+
if isinstance(e, MSVSProject):
|
275
|
+
if e.dependencies:
|
276
|
+
f.write('\tProjectSection(ProjectDependencies) = postProject\r\n')
|
277
|
+
for d in e.dependencies:
|
278
|
+
f.write('\t\t%s = %s\r\n' % (d.get_guid(), d.get_guid()))
|
279
|
+
f.write('\tEndProjectSection\r\n')
|
280
|
+
|
281
|
+
f.write('EndProject\r\n')
|
282
|
+
|
283
|
+
# Global section
|
284
|
+
f.write('Global\r\n')
|
285
|
+
|
286
|
+
# Configurations (variants)
|
287
|
+
f.write('\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\r\n')
|
288
|
+
for v in self.variants:
|
289
|
+
f.write('\t\t%s = %s\r\n' % (v, v))
|
290
|
+
f.write('\tEndGlobalSection\r\n')
|
291
|
+
|
292
|
+
# Sort config guids for easier diffing of solution changes.
|
293
|
+
config_guids = []
|
294
|
+
config_guids_overrides = {}
|
295
|
+
for e in all_entries:
|
296
|
+
if isinstance(e, MSVSProject):
|
297
|
+
config_guids.append(e.get_guid())
|
298
|
+
config_guids_overrides[e.get_guid()] = e.config_platform_overrides
|
299
|
+
config_guids.sort()
|
300
|
+
|
301
|
+
f.write('\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\r\n')
|
302
|
+
for g in config_guids:
|
303
|
+
for v in self.variants:
|
304
|
+
nv = config_guids_overrides[g].get(v, v)
|
305
|
+
# Pick which project configuration to build for this solution
|
306
|
+
# configuration.
|
307
|
+
f.write('\t\t%s.%s.ActiveCfg = %s\r\n' % (
|
308
|
+
g, # Project GUID
|
309
|
+
v, # Solution build configuration
|
310
|
+
nv, # Project build config for that solution config
|
311
|
+
))
|
312
|
+
|
313
|
+
# Enable project in this solution configuration.
|
314
|
+
f.write('\t\t%s.%s.Build.0 = %s\r\n' % (
|
315
|
+
g, # Project GUID
|
316
|
+
v, # Solution build configuration
|
317
|
+
nv, # Project build config for that solution config
|
318
|
+
))
|
319
|
+
f.write('\tEndGlobalSection\r\n')
|
320
|
+
|
321
|
+
# TODO(rspangler): Should be able to configure this stuff too (though I've
|
322
|
+
# never seen this be any different)
|
323
|
+
f.write('\tGlobalSection(SolutionProperties) = preSolution\r\n')
|
324
|
+
f.write('\t\tHideSolutionNode = FALSE\r\n')
|
325
|
+
f.write('\tEndGlobalSection\r\n')
|
326
|
+
|
327
|
+
# Folder mappings
|
328
|
+
# Omit this section if there are no folders
|
329
|
+
if any([e.entries for e in all_entries if isinstance(e, MSVSFolder)]):
|
330
|
+
f.write('\tGlobalSection(NestedProjects) = preSolution\r\n')
|
331
|
+
for e in all_entries:
|
332
|
+
if not isinstance(e, MSVSFolder):
|
333
|
+
continue # Does not apply to projects, only folders
|
334
|
+
for subentry in e.entries:
|
335
|
+
f.write('\t\t%s = %s\r\n' % (subentry.get_guid(), e.get_guid()))
|
336
|
+
f.write('\tEndGlobalSection\r\n')
|
337
|
+
|
338
|
+
f.write('EndGlobal\r\n')
|
339
|
+
|
340
|
+
f.close()
|
@@ -0,0 +1,208 @@
|
|
1
|
+
# Copyright (c) 2012 Google Inc. All rights reserved.
|
2
|
+
# Use of this source code is governed by a BSD-style license that can be
|
3
|
+
# found in the LICENSE file.
|
4
|
+
|
5
|
+
"""Visual Studio project reader/writer."""
|
6
|
+
|
7
|
+
import gyp.common
|
8
|
+
import gyp.easy_xml as easy_xml
|
9
|
+
|
10
|
+
#------------------------------------------------------------------------------
|
11
|
+
|
12
|
+
|
13
|
+
class Tool(object):
|
14
|
+
"""Visual Studio tool."""
|
15
|
+
|
16
|
+
def __init__(self, name, attrs=None):
|
17
|
+
"""Initializes the tool.
|
18
|
+
|
19
|
+
Args:
|
20
|
+
name: Tool name.
|
21
|
+
attrs: Dict of tool attributes; may be None.
|
22
|
+
"""
|
23
|
+
self._attrs = attrs or {}
|
24
|
+
self._attrs['Name'] = name
|
25
|
+
|
26
|
+
def _GetSpecification(self):
|
27
|
+
"""Creates an element for the tool.
|
28
|
+
|
29
|
+
Returns:
|
30
|
+
A new xml.dom.Element for the tool.
|
31
|
+
"""
|
32
|
+
return ['Tool', self._attrs]
|
33
|
+
|
34
|
+
class Filter(object):
|
35
|
+
"""Visual Studio filter - that is, a virtual folder."""
|
36
|
+
|
37
|
+
def __init__(self, name, contents=None):
|
38
|
+
"""Initializes the folder.
|
39
|
+
|
40
|
+
Args:
|
41
|
+
name: Filter (folder) name.
|
42
|
+
contents: List of filenames and/or Filter objects contained.
|
43
|
+
"""
|
44
|
+
self.name = name
|
45
|
+
self.contents = list(contents or [])
|
46
|
+
|
47
|
+
|
48
|
+
#------------------------------------------------------------------------------
|
49
|
+
|
50
|
+
|
51
|
+
class Writer(object):
|
52
|
+
"""Visual Studio XML project writer."""
|
53
|
+
|
54
|
+
def __init__(self, project_path, version, name, guid=None, platforms=None):
|
55
|
+
"""Initializes the project.
|
56
|
+
|
57
|
+
Args:
|
58
|
+
project_path: Path to the project file.
|
59
|
+
version: Format version to emit.
|
60
|
+
name: Name of the project.
|
61
|
+
guid: GUID to use for project, if not None.
|
62
|
+
platforms: Array of string, the supported platforms. If null, ['Win32']
|
63
|
+
"""
|
64
|
+
self.project_path = project_path
|
65
|
+
self.version = version
|
66
|
+
self.name = name
|
67
|
+
self.guid = guid
|
68
|
+
|
69
|
+
# Default to Win32 for platforms.
|
70
|
+
if not platforms:
|
71
|
+
platforms = ['Win32']
|
72
|
+
|
73
|
+
# Initialize the specifications of the various sections.
|
74
|
+
self.platform_section = ['Platforms']
|
75
|
+
for platform in platforms:
|
76
|
+
self.platform_section.append(['Platform', {'Name': platform}])
|
77
|
+
self.tool_files_section = ['ToolFiles']
|
78
|
+
self.configurations_section = ['Configurations']
|
79
|
+
self.files_section = ['Files']
|
80
|
+
|
81
|
+
# Keep a dict keyed on filename to speed up access.
|
82
|
+
self.files_dict = dict()
|
83
|
+
|
84
|
+
def AddToolFile(self, path):
|
85
|
+
"""Adds a tool file to the project.
|
86
|
+
|
87
|
+
Args:
|
88
|
+
path: Relative path from project to tool file.
|
89
|
+
"""
|
90
|
+
self.tool_files_section.append(['ToolFile', {'RelativePath': path}])
|
91
|
+
|
92
|
+
def _GetSpecForConfiguration(self, config_type, config_name, attrs, tools):
|
93
|
+
"""Returns the specification for a configuration.
|
94
|
+
|
95
|
+
Args:
|
96
|
+
config_type: Type of configuration node.
|
97
|
+
config_name: Configuration name.
|
98
|
+
attrs: Dict of configuration attributes; may be None.
|
99
|
+
tools: List of tools (strings or Tool objects); may be None.
|
100
|
+
Returns:
|
101
|
+
"""
|
102
|
+
# Handle defaults
|
103
|
+
if not attrs:
|
104
|
+
attrs = {}
|
105
|
+
if not tools:
|
106
|
+
tools = []
|
107
|
+
|
108
|
+
# Add configuration node and its attributes
|
109
|
+
node_attrs = attrs.copy()
|
110
|
+
node_attrs['Name'] = config_name
|
111
|
+
specification = [config_type, node_attrs]
|
112
|
+
|
113
|
+
# Add tool nodes and their attributes
|
114
|
+
if tools:
|
115
|
+
for t in tools:
|
116
|
+
if isinstance(t, Tool):
|
117
|
+
specification.append(t._GetSpecification())
|
118
|
+
else:
|
119
|
+
specification.append(Tool(t)._GetSpecification())
|
120
|
+
return specification
|
121
|
+
|
122
|
+
|
123
|
+
def AddConfig(self, name, attrs=None, tools=None):
|
124
|
+
"""Adds a configuration to the project.
|
125
|
+
|
126
|
+
Args:
|
127
|
+
name: Configuration name.
|
128
|
+
attrs: Dict of configuration attributes; may be None.
|
129
|
+
tools: List of tools (strings or Tool objects); may be None.
|
130
|
+
"""
|
131
|
+
spec = self._GetSpecForConfiguration('Configuration', name, attrs, tools)
|
132
|
+
self.configurations_section.append(spec)
|
133
|
+
|
134
|
+
def _AddFilesToNode(self, parent, files):
|
135
|
+
"""Adds files and/or filters to the parent node.
|
136
|
+
|
137
|
+
Args:
|
138
|
+
parent: Destination node
|
139
|
+
files: A list of Filter objects and/or relative paths to files.
|
140
|
+
|
141
|
+
Will call itself recursively, if the files list contains Filter objects.
|
142
|
+
"""
|
143
|
+
for f in files:
|
144
|
+
if isinstance(f, Filter):
|
145
|
+
node = ['Filter', {'Name': f.name}]
|
146
|
+
self._AddFilesToNode(node, f.contents)
|
147
|
+
else:
|
148
|
+
node = ['File', {'RelativePath': f}]
|
149
|
+
self.files_dict[f] = node
|
150
|
+
parent.append(node)
|
151
|
+
|
152
|
+
def AddFiles(self, files):
|
153
|
+
"""Adds files to the project.
|
154
|
+
|
155
|
+
Args:
|
156
|
+
files: A list of Filter objects and/or relative paths to files.
|
157
|
+
|
158
|
+
This makes a copy of the file/filter tree at the time of this call. If you
|
159
|
+
later add files to a Filter object which was passed into a previous call
|
160
|
+
to AddFiles(), it will not be reflected in this project.
|
161
|
+
"""
|
162
|
+
self._AddFilesToNode(self.files_section, files)
|
163
|
+
# TODO(rspangler) This also doesn't handle adding files to an existing
|
164
|
+
# filter. That is, it doesn't merge the trees.
|
165
|
+
|
166
|
+
def AddFileConfig(self, path, config, attrs=None, tools=None):
|
167
|
+
"""Adds a configuration to a file.
|
168
|
+
|
169
|
+
Args:
|
170
|
+
path: Relative path to the file.
|
171
|
+
config: Name of configuration to add.
|
172
|
+
attrs: Dict of configuration attributes; may be None.
|
173
|
+
tools: List of tools (strings or Tool objects); may be None.
|
174
|
+
|
175
|
+
Raises:
|
176
|
+
ValueError: Relative path does not match any file added via AddFiles().
|
177
|
+
"""
|
178
|
+
# Find the file node with the right relative path
|
179
|
+
parent = self.files_dict.get(path)
|
180
|
+
if not parent:
|
181
|
+
raise ValueError('AddFileConfig: file "%s" not in project.' % path)
|
182
|
+
|
183
|
+
# Add the config to the file node
|
184
|
+
spec = self._GetSpecForConfiguration('FileConfiguration', config, attrs,
|
185
|
+
tools)
|
186
|
+
parent.append(spec)
|
187
|
+
|
188
|
+
def WriteIfChanged(self):
|
189
|
+
"""Writes the project file."""
|
190
|
+
# First create XML content definition
|
191
|
+
content = [
|
192
|
+
'VisualStudioProject',
|
193
|
+
{'ProjectType': 'Visual C++',
|
194
|
+
'Version': self.version.ProjectVersion(),
|
195
|
+
'Name': self.name,
|
196
|
+
'ProjectGUID': self.guid,
|
197
|
+
'RootNamespace': self.name,
|
198
|
+
'Keyword': 'Win32Proj'
|
199
|
+
},
|
200
|
+
self.platform_section,
|
201
|
+
self.tool_files_section,
|
202
|
+
self.configurations_section,
|
203
|
+
['References'], # empty section
|
204
|
+
self.files_section,
|
205
|
+
['Globals'] # empty section
|
206
|
+
]
|
207
|
+
easy_xml.WriteXmlIfChanged(content, self.project_path,
|
208
|
+
encoding="Windows-1252")
|