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

Side by Side Diff: scons-2.0.1/engine/SCons/Tool/msvs.py

Issue 6711079: Added an unmodified copy of SCons to third_party. (Closed) Base URL: svn://svn.chromium.org/native_client/trunk/src/third_party/
Patch Set: '' Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « scons-2.0.1/engine/SCons/Tool/msvc.py ('k') | scons-2.0.1/engine/SCons/Tool/mwcc.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 """SCons.Tool.msvs
2
3 Tool-specific initialization for Microsoft Visual Studio project files.
4
5 There normally shouldn't be any need to import this module directly.
6 It will usually be imported through the generic SCons.Tool.Tool()
7 selection method.
8
9 """
10
11 #
12 # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 The S Cons Foundation
13 #
14 # Permission is hereby granted, free of charge, to any person obtaining
15 # a copy of this software and associated documentation files (the
16 # "Software"), to deal in the Software without restriction, including
17 # without limitation the rights to use, copy, modify, merge, publish,
18 # distribute, sublicense, and/or sell copies of the Software, and to
19 # permit persons to whom the Software is furnished to do so, subject to
20 # the following conditions:
21 #
22 # The above copyright notice and this permission notice shall be included
23 # in all copies or substantial portions of the Software.
24 #
25 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
26 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
27 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32
33 __revision__ = "src/engine/SCons/Tool/msvs.py 5134 2010/08/16 23:02:40 bdeegan"
34
35 import SCons.compat
36
37 import base64
38 import hashlib
39 import ntpath
40 import os
41 # compat layer imports "cPickle" for us if it's available.
42 import pickle
43 import re
44 import sys
45
46 import SCons.Builder
47 import SCons.Node.FS
48 import SCons.Platform.win32
49 import SCons.Script.SConscript
50 import SCons.Util
51 import SCons.Warnings
52
53 from MSCommon import msvc_exists, msvc_setup_env_once
54 from SCons.Defaults import processDefines
55
56 ##############################################################################
57 # Below here are the classes and functions for generation of
58 # DSP/DSW/SLN/VCPROJ files.
59 ##############################################################################
60
61 def xmlify(s):
62 s = s.replace("&", "&") # do this first
63 s = s.replace("'", "'")
64 s = s.replace('"', """)
65 return s
66
67 external_makefile_guid = '{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}'
68
69 def _generateGUID(slnfile, name):
70 """This generates a dummy GUID for the sln file to use. It is
71 based on the MD5 signatures of the sln filename plus the name of
72 the project. It basically just needs to be unique, and not
73 change with each invocation."""
74 m = hashlib.md5()
75 # Normalize the slnfile path to a Windows path (\ separators) so
76 # the generated file has a consistent GUID even if we generate
77 # it on a non-Windows platform.
78 m.update(ntpath.normpath(str(slnfile)) + str(name))
79 solution = m.hexdigest().upper()
80 # convert most of the signature to GUID form (discard the rest)
81 solution = "{" + solution[:8] + "-" + solution[8:12] + "-" + solution[12:16] + "-" + solution[16:20] + "-" + solution[20:32] + "}"
82 return solution
83
84 version_re = re.compile(r'(\d+\.\d+)(.*)')
85
86 def msvs_parse_version(s):
87 """
88 Split a Visual Studio version, which may in fact be something like
89 '7.0Exp', into is version number (returned as a float) and trailing
90 "suite" portion.
91 """
92 num, suite = version_re.match(s).groups()
93 return float(num), suite
94
95 # This is how we re-invoke SCons from inside MSVS Project files.
96 # The problem is that we might have been invoked as either scons.bat
97 # or scons.py. If we were invoked directly as scons.py, then we could
98 # use sys.argv[0] to find the SCons "executable," but that doesn't work
99 # if we were invoked as scons.bat, which uses "python -c" to execute
100 # things and ends up with "-c" as sys.argv[0]. Consequently, we have
101 # the MSVS Project file invoke SCons the same way that scons.bat does,
102 # which works regardless of how we were invoked.
103 def getExecScriptMain(env, xml=None):
104 scons_home = env.get('SCONS_HOME')
105 if not scons_home and 'SCONS_LIB_DIR' in os.environ:
106 scons_home = os.environ['SCONS_LIB_DIR']
107 if scons_home:
108 exec_script_main = "from os.path import join; import sys; sys.path = [ r '%s' ] + sys.path; import SCons.Script; SCons.Script.main()" % scons_home
109 else:
110 version = SCons.__version__
111 exec_script_main = "from os.path import join; import sys; sys.path = [ j oin(sys.prefix, 'Lib', 'site-packages', 'scons-%(version)s'), join(sys.prefix, ' scons-%(version)s'), join(sys.prefix, 'Lib', 'site-packages', 'scons'), join(sys .prefix, 'scons') ] + sys.path; import SCons.Script; SCons.Script.main()" % loca ls()
112 if xml:
113 exec_script_main = xmlify(exec_script_main)
114 return exec_script_main
115
116 # The string for the Python executable we tell the Project file to use
117 # is either sys.executable or, if an external PYTHON_ROOT environment
118 # variable exists, $(PYTHON)ROOT\\python.exe (generalized a little to
119 # pluck the actual executable name from sys.executable).
120 try:
121 python_root = os.environ['PYTHON_ROOT']
122 except KeyError:
123 python_executable = sys.executable
124 else:
125 python_executable = os.path.join('$$(PYTHON_ROOT)',
126 os.path.split(sys.executable)[1])
127
128 class Config(object):
129 pass
130
131 def splitFully(path):
132 dir, base = os.path.split(path)
133 if dir and dir != '' and dir != path:
134 return splitFully(dir)+[base]
135 if base == '':
136 return []
137 return [base]
138
139 def makeHierarchy(sources):
140 '''Break a list of files into a hierarchy; for each value, if it is a string ,
141 then it is a file. If it is a dictionary, it is a folder. The string is
142 the original path of the file.'''
143
144 hierarchy = {}
145 for file in sources:
146 path = splitFully(file)
147 if len(path):
148 dict = hierarchy
149 for part in path[:-1]:
150 if part not in dict:
151 dict[part] = {}
152 dict = dict[part]
153 dict[path[-1]] = file
154 #else:
155 # print 'Warning: failed to decompose path for '+str(file)
156 return hierarchy
157
158 class _DSPGenerator(object):
159 """ Base class for DSP generators """
160
161 srcargs = [
162 'srcs',
163 'incs',
164 'localincs',
165 'resources',
166 'misc']
167
168 def __init__(self, dspfile, source, env):
169 self.dspfile = str(dspfile)
170 try:
171 get_abspath = dspfile.get_abspath
172 except AttributeError:
173 self.dspabs = os.path.abspath(dspfile)
174 else:
175 self.dspabs = get_abspath()
176
177 if 'variant' not in env:
178 raise SCons.Errors.InternalError("You must specify a 'variant' argum ent (i.e. 'Debug' or " +\
179 "'Release') to create an MSVSProject.")
180 elif SCons.Util.is_String(env['variant']):
181 variants = [env['variant']]
182 elif SCons.Util.is_List(env['variant']):
183 variants = env['variant']
184
185 if 'buildtarget' not in env or env['buildtarget'] == None:
186 buildtarget = ['']
187 elif SCons.Util.is_String(env['buildtarget']):
188 buildtarget = [env['buildtarget']]
189 elif SCons.Util.is_List(env['buildtarget']):
190 if len(env['buildtarget']) != len(variants):
191 raise SCons.Errors.InternalError("Sizes of 'buildtarget' and 'va riant' lists must be the same.")
192 buildtarget = []
193 for bt in env['buildtarget']:
194 if SCons.Util.is_String(bt):
195 buildtarget.append(bt)
196 else:
197 buildtarget.append(bt.get_abspath())
198 else:
199 buildtarget = [env['buildtarget'].get_abspath()]
200 if len(buildtarget) == 1:
201 bt = buildtarget[0]
202 buildtarget = []
203 for _ in variants:
204 buildtarget.append(bt)
205
206 if 'outdir' not in env or env['outdir'] == None:
207 outdir = ['']
208 elif SCons.Util.is_String(env['outdir']):
209 outdir = [env['outdir']]
210 elif SCons.Util.is_List(env['outdir']):
211 if len(env['outdir']) != len(variants):
212 raise SCons.Errors.InternalError("Sizes of 'outdir' and 'variant ' lists must be the same.")
213 outdir = []
214 for s in env['outdir']:
215 if SCons.Util.is_String(s):
216 outdir.append(s)
217 else:
218 outdir.append(s.get_abspath())
219 else:
220 outdir = [env['outdir'].get_abspath()]
221 if len(outdir) == 1:
222 s = outdir[0]
223 outdir = []
224 for v in variants:
225 outdir.append(s)
226
227 if 'runfile' not in env or env['runfile'] == None:
228 runfile = buildtarget[-1:]
229 elif SCons.Util.is_String(env['runfile']):
230 runfile = [env['runfile']]
231 elif SCons.Util.is_List(env['runfile']):
232 if len(env['runfile']) != len(variants):
233 raise SCons.Errors.InternalError("Sizes of 'runfile' and 'varian t' lists must be the same.")
234 runfile = []
235 for s in env['runfile']:
236 if SCons.Util.is_String(s):
237 runfile.append(s)
238 else:
239 runfile.append(s.get_abspath())
240 else:
241 runfile = [env['runfile'].get_abspath()]
242 if len(runfile) == 1:
243 s = runfile[0]
244 runfile = []
245 for v in variants:
246 runfile.append(s)
247
248 self.sconscript = env['MSVSSCONSCRIPT']
249
250 cmdargs = env.get('cmdargs', '')
251
252 self.env = env
253
254 if 'name' in self.env:
255 self.name = self.env['name']
256 else:
257 self.name = os.path.basename(SCons.Util.splitext(self.dspfile)[0])
258 self.name = self.env.subst(self.name)
259
260 sourcenames = [
261 'Source Files',
262 'Header Files',
263 'Local Headers',
264 'Resource Files',
265 'Other Files']
266
267 self.sources = {}
268 for n in sourcenames:
269 self.sources[n] = []
270
271 self.configs = {}
272
273 self.nokeep = 0
274 if 'nokeep' in env and env['variant'] != 0:
275 self.nokeep = 1
276
277 if self.nokeep == 0 and os.path.exists(self.dspabs):
278 self.Parse()
279
280 for t in zip(sourcenames,self.srcargs):
281 if t[1] in self.env:
282 if SCons.Util.is_List(self.env[t[1]]):
283 for i in self.env[t[1]]:
284 if not i in self.sources[t[0]]:
285 self.sources[t[0]].append(i)
286 else:
287 if not self.env[t[1]] in self.sources[t[0]]:
288 self.sources[t[0]].append(self.env[t[1]])
289
290 for n in sourcenames:
291 #TODO 2.4: compat layer supports sorted(key=) but not sort(key=)
292 #TODO 2.4: self.sources[n].sort(key=lambda a: a.lower())
293 self.sources[n] = sorted(self.sources[n], key=lambda a: a.lower())
294
295 def AddConfig(self, variant, buildtarget, outdir, runfile, cmdargs, dspf ile=dspfile):
296 config = Config()
297 config.buildtarget = buildtarget
298 config.outdir = outdir
299 config.cmdargs = cmdargs
300 config.runfile = runfile
301
302 match = re.match('(.*)\|(.*)', variant)
303 if match:
304 config.variant = match.group(1)
305 config.platform = match.group(2)
306 else:
307 config.variant = variant
308 config.platform = 'Win32'
309
310 self.configs[variant] = config
311 print "Adding '" + self.name + ' - ' + config.variant + '|' + config .platform + "' to '" + str(dspfile) + "'"
312
313 for i in range(len(variants)):
314 AddConfig(self, variants[i], buildtarget[i], outdir[i], runfile[i], cmdargs)
315
316 self.platforms = []
317 for key in self.configs.keys():
318 platform = self.configs[key].platform
319 if not platform in self.platforms:
320 self.platforms.append(platform)
321
322 def Build(self):
323 pass
324
325 V6DSPHeader = """\
326 # Microsoft Developer Studio Project File - Name="%(name)s" - Package Owner=<4>
327 # Microsoft Developer Studio Generated Build File, Format Version 6.00
328 # ** DO NOT EDIT **
329
330 # TARGTYPE "Win32 (x86) External Target" 0x0106
331
332 CFG=%(name)s - Win32 %(confkey)s
333 !MESSAGE This is not a valid makefile. To build this project using NMAKE,
334 !MESSAGE use the Export Makefile command and run
335 !MESSAGE
336 !MESSAGE NMAKE /f "%(name)s.mak".
337 !MESSAGE
338 !MESSAGE You can specify a configuration when running NMAKE
339 !MESSAGE by defining the macro CFG on the command line. For example:
340 !MESSAGE
341 !MESSAGE NMAKE /f "%(name)s.mak" CFG="%(name)s - Win32 %(confkey)s"
342 !MESSAGE
343 !MESSAGE Possible choices for configuration are:
344 !MESSAGE
345 """
346
347 class _GenerateV6DSP(_DSPGenerator):
348 """Generates a Project file for MSVS 6.0"""
349
350 def PrintHeader(self):
351 # pick a default config
352 confkeys = sorted(self.configs.keys())
353
354 name = self.name
355 confkey = confkeys[0]
356
357 self.file.write(V6DSPHeader % locals())
358
359 for kind in confkeys:
360 self.file.write('!MESSAGE "%s - Win32 %s" (based on "Win32 (x86) Ext ernal Target")\n' % (name, kind))
361
362 self.file.write('!MESSAGE \n\n')
363
364 def PrintProject(self):
365 name = self.name
366 self.file.write('# Begin Project\n'
367 '# PROP AllowPerConfigDependencies 0\n'
368 '# PROP Scc_ProjName ""\n'
369 '# PROP Scc_LocalPath ""\n\n')
370
371 first = 1
372 confkeys = sorted(self.configs.keys())
373 for kind in confkeys:
374 outdir = self.configs[kind].outdir
375 buildtarget = self.configs[kind].buildtarget
376 if first == 1:
377 self.file.write('!IF "$(CFG)" == "%s - Win32 %s"\n\n' % (name, kind))
378 first = 0
379 else:
380 self.file.write('\n!ELSEIF "$(CFG)" == "%s - Win32 %s"\n\n' % ( name, kind))
381
382 env_has_buildtarget = 'MSVSBUILDTARGET' in self.env
383 if not env_has_buildtarget:
384 self.env['MSVSBUILDTARGET'] = buildtarget
385
386 # have to write this twice, once with the BASE settings, and once wi thout
387 for base in ("BASE ",""):
388 self.file.write('# PROP %sUse_MFC 0\n'
389 '# PROP %sUse_Debug_Libraries ' % (base, base))
390 if kind.lower().find('debug') < 0:
391 self.file.write('0\n')
392 else:
393 self.file.write('1\n')
394 self.file.write('# PROP %sOutput_Dir "%s"\n'
395 '# PROP %sIntermediate_Dir "%s"\n' % (base,outdi r,base,outdir))
396 cmd = 'echo Starting SCons && ' + self.env.subst('$MSVSBUILDCOM' , 1)
397 self.file.write('# PROP %sCmd_Line "%s"\n'
398 '# PROP %sRebuild_Opt "-c && %s"\n'
399 '# PROP %sTarget_File "%s"\n'
400 '# PROP %sBsc_Name ""\n'
401 '# PROP %sTarget_Dir ""\n'\
402 %(base,cmd,base,cmd,base,buildtarget,base,base))
403
404 if not env_has_buildtarget:
405 del self.env['MSVSBUILDTARGET']
406
407 self.file.write('\n!ENDIF\n\n'
408 '# Begin Target\n\n')
409 for kind in confkeys:
410 self.file.write('# Name "%s - Win32 %s"\n' % (name,kind))
411 self.file.write('\n')
412 first = 0
413 for kind in confkeys:
414 if first == 0:
415 self.file.write('!IF "$(CFG)" == "%s - Win32 %s"\n\n' % (name,k ind))
416 first = 1
417 else:
418 self.file.write('!ELSEIF "$(CFG)" == "%s - Win32 %s"\n\n' % (na me,kind))
419 self.file.write('!ENDIF \n\n')
420 self.PrintSourceFiles()
421 self.file.write('# End Target\n'
422 '# End Project\n')
423
424 if self.nokeep == 0:
425 # now we pickle some data and add it to the file -- MSDEV will ignor e it.
426 pdata = pickle.dumps(self.configs,1)
427 pdata = base64.encodestring(pdata)
428 self.file.write(pdata + '\n')
429 pdata = pickle.dumps(self.sources,1)
430 pdata = base64.encodestring(pdata)
431 self.file.write(pdata + '\n')
432
433 def PrintSourceFiles(self):
434 categories = {'Source Files': 'cpp|c|cxx|l|y|def|odl|idl|hpj|bat',
435 'Header Files': 'h|hpp|hxx|hm|inl',
436 'Local Headers': 'h|hpp|hxx|hm|inl',
437 'Resource Files': 'r|rc|ico|cur|bmp|dlg|rc2|rct|bin|cnt|rt f|gif|jpg|jpeg|jpe',
438 'Other Files': ''}
439
440 for kind in sorted(categories.keys(), key=lambda a: a.lower()):
441 if not self.sources[kind]:
442 continue # skip empty groups
443
444 self.file.write('# Begin Group "' + kind + '"\n\n')
445 typelist = categories[kind].replace('|', ';')
446 self.file.write('# PROP Default_Filter "' + typelist + '"\n')
447
448 for file in self.sources[kind]:
449 file = os.path.normpath(file)
450 self.file.write('# Begin Source File\n\n'
451 'SOURCE="' + file + '"\n'
452 '# End Source File\n')
453 self.file.write('# End Group\n')
454
455 # add the SConscript file outside of the groups
456 self.file.write('# Begin Source File\n\n'
457 'SOURCE="' + str(self.sconscript) + '"\n'
458 '# End Source File\n')
459
460 def Parse(self):
461 try:
462 dspfile = open(self.dspabs,'r')
463 except IOError:
464 return # doesn't exist yet, so can't add anything to configs.
465
466 line = dspfile.readline()
467 while line:
468 if line.find("# End Project") > -1:
469 break
470 line = dspfile.readline()
471
472 line = dspfile.readline()
473 datas = line
474 while line and line != '\n':
475 line = dspfile.readline()
476 datas = datas + line
477
478 # OK, we've found our little pickled cache of data.
479 try:
480 datas = base64.decodestring(datas)
481 data = pickle.loads(datas)
482 except KeyboardInterrupt:
483 raise
484 except:
485 return # unable to unpickle any data for some reason
486
487 self.configs.update(data)
488
489 data = None
490 line = dspfile.readline()
491 datas = line
492 while line and line != '\n':
493 line = dspfile.readline()
494 datas = datas + line
495
496 # OK, we've found our little pickled cache of data.
497 # it has a "# " in front of it, so we strip that.
498 try:
499 datas = base64.decodestring(datas)
500 data = pickle.loads(datas)
501 except KeyboardInterrupt:
502 raise
503 except:
504 return # unable to unpickle any data for some reason
505
506 self.sources.update(data)
507
508 def Build(self):
509 try:
510 self.file = open(self.dspabs,'w')
511 except IOError, detail:
512 raise SCons.Errors.InternalError('Unable to open "' + self.dspabs + '" for writing:' + str(detail))
513 else:
514 self.PrintHeader()
515 self.PrintProject()
516 self.file.close()
517
518 V7DSPHeader = """\
519 <?xml version="1.0" encoding = "%(encoding)s"?>
520 <VisualStudioProject
521 \tProjectType="Visual C++"
522 \tVersion="%(versionstr)s"
523 \tName="%(name)s"
524 %(scc_attrs)s
525 \tKeyword="MakeFileProj">
526 """
527
528 V7DSPConfiguration = """\
529 \t\t<Configuration
530 \t\t\tName="%(variant)s|%(platform)s"
531 \t\t\tOutputDirectory="%(outdir)s"
532 \t\t\tIntermediateDirectory="%(outdir)s"
533 \t\t\tConfigurationType="0"
534 \t\t\tUseOfMFC="0"
535 \t\t\tATLMinimizesCRunTimeLibraryUsage="FALSE">
536 \t\t\t<Tool
537 \t\t\t\tName="VCNMakeTool"
538 \t\t\t\tBuildCommandLine="%(buildcmd)s"
539 \t\t\t\tCleanCommandLine="%(cleancmd)s"
540 \t\t\t\tRebuildCommandLine="%(rebuildcmd)s"
541 \t\t\t\tOutput="%(runfile)s"/>
542 \t\t</Configuration>
543 """
544
545 V8DSPHeader = """\
546 <?xml version="1.0" encoding="%(encoding)s"?>
547 <VisualStudioProject
548 \tProjectType="Visual C++"
549 \tVersion="%(versionstr)s"
550 \tName="%(name)s"
551 %(scc_attrs)s
552 \tRootNamespace="%(name)s"
553 \tKeyword="MakeFileProj">
554 """
555
556 V8DSPConfiguration = """\
557 \t\t<Configuration
558 \t\t\tName="%(variant)s|%(platform)s"
559 \t\t\tConfigurationType="0"
560 \t\t\tUseOfMFC="0"
561 \t\t\tATLMinimizesCRunTimeLibraryUsage="false"
562 \t\t\t>
563 \t\t\t<Tool
564 \t\t\t\tName="VCNMakeTool"
565 \t\t\t\tBuildCommandLine="%(buildcmd)s"
566 \t\t\t\tReBuildCommandLine="%(rebuildcmd)s"
567 \t\t\t\tCleanCommandLine="%(cleancmd)s"
568 \t\t\t\tOutput="%(runfile)s"
569 \t\t\t\tPreprocessorDefinitions="%(preprocdefs)s"
570 \t\t\t\tIncludeSearchPath="%(includepath)s"
571 \t\t\t\tForcedIncludes=""
572 \t\t\t\tAssemblySearchPath=""
573 \t\t\t\tForcedUsingAssemblies=""
574 \t\t\t\tCompileAsManaged=""
575 \t\t\t/>
576 \t\t</Configuration>
577 """
578 class _GenerateV7DSP(_DSPGenerator):
579 """Generates a Project file for MSVS .NET"""
580
581 def __init__(self, dspfile, source, env):
582 _DSPGenerator.__init__(self, dspfile, source, env)
583 self.version = env['MSVS_VERSION']
584 self.version_num, self.suite = msvs_parse_version(self.version)
585 if self.version_num >= 8.0:
586 self.versionstr = '8.00'
587 self.dspheader = V8DSPHeader
588 self.dspconfiguration = V8DSPConfiguration
589 else:
590 if self.version_num >= 7.1:
591 self.versionstr = '7.10'
592 else:
593 self.versionstr = '7.00'
594 self.dspheader = V7DSPHeader
595 self.dspconfiguration = V7DSPConfiguration
596 self.file = None
597
598 def PrintHeader(self):
599 env = self.env
600 versionstr = self.versionstr
601 name = self.name
602 encoding = self.env.subst('$MSVSENCODING')
603 scc_provider = env.get('MSVS_SCC_PROVIDER', '')
604 scc_project_name = env.get('MSVS_SCC_PROJECT_NAME', '')
605 scc_aux_path = env.get('MSVS_SCC_AUX_PATH', '')
606 scc_local_path = env.get('MSVS_SCC_LOCAL_PATH', '')
607 project_guid = env.get('MSVS_PROJECT_GUID', '')
608 if self.version_num >= 8.0 and not project_guid:
609 project_guid = _generateGUID(self.dspfile, '')
610 if scc_provider != '':
611 scc_attrs = ('\tProjectGUID="%s"\n'
612 '\tSccProjectName="%s"\n'
613 '\tSccAuxPath="%s"\n'
614 '\tSccLocalPath="%s"\n'
615 '\tSccProvider="%s"' % (project_guid, scc_project_name, scc_aux_path, scc_local_path, scc_provider))
616 else:
617 scc_attrs = ('\tProjectGUID="%s"\n'
618 '\tSccProjectName="%s"\n'
619 '\tSccLocalPath="%s"' % (project_guid, scc_project_name , scc_local_path))
620
621 self.file.write(self.dspheader % locals())
622
623 self.file.write('\t<Platforms>\n')
624 for platform in self.platforms:
625 self.file.write(
626 '\t\t<Platform\n'
627 '\t\t\tName="%s"/>\n' % platform)
628 self.file.write('\t</Platforms>\n')
629
630 if self.version_num >= 8.0:
631 self.file.write('\t<ToolFiles>\n'
632 '\t</ToolFiles>\n')
633
634 def PrintProject(self):
635 self.file.write('\t<Configurations>\n')
636
637 confkeys = sorted(self.configs.keys())
638 for kind in confkeys:
639 variant = self.configs[kind].variant
640 platform = self.configs[kind].platform
641 outdir = self.configs[kind].outdir
642 buildtarget = self.configs[kind].buildtarget
643 runfile = self.configs[kind].runfile
644 cmdargs = self.configs[kind].cmdargs
645
646 env_has_buildtarget = 'MSVSBUILDTARGET' in self.env
647 if not env_has_buildtarget:
648 self.env['MSVSBUILDTARGET'] = buildtarget
649
650 starting = 'echo Starting SCons && '
651 if cmdargs:
652 cmdargs = ' ' + cmdargs
653 else:
654 cmdargs = ''
655 buildcmd = xmlify(starting + self.env.subst('$MSVSBUILDCOM', 1) + cmdargs)
656 rebuildcmd = xmlify(starting + self.env.subst('$MSVSREBUILDCOM', 1) + cmdargs)
657 cleancmd = xmlify(starting + self.env.subst('$MSVSCLEANCOM', 1) + cmdargs)
658
659 preprocdefs = xmlify(';'.join(processDefines(self.env.get('CPPDEFINE S', []))))
660 includepath = xmlify(';'.join(self.env.get('CPPPATH', [])))
661
662 if not env_has_buildtarget:
663 del self.env['MSVSBUILDTARGET']
664
665 self.file.write(self.dspconfiguration % locals())
666
667 self.file.write('\t</Configurations>\n')
668
669 if self.version_num >= 7.1:
670 self.file.write('\t<References>\n'
671 '\t</References>\n')
672
673 self.PrintSourceFiles()
674
675 self.file.write('</VisualStudioProject>\n')
676
677 if self.nokeep == 0:
678 # now we pickle some data and add it to the file -- MSDEV will ignor e it.
679 pdata = pickle.dumps(self.configs,1)
680 pdata = base64.encodestring(pdata)
681 self.file.write('<!-- SCons Data:\n' + pdata + '\n')
682 pdata = pickle.dumps(self.sources,1)
683 pdata = base64.encodestring(pdata)
684 self.file.write(pdata + '-->\n')
685
686 def printSources(self, hierarchy, commonprefix):
687 sorteditems = sorted(hierarchy.items(), key=lambda a: a[0].lower())
688
689 # First folders, then files
690 for key, value in sorteditems:
691 if SCons.Util.is_Dict(value):
692 self.file.write('\t\t\t<Filter\n'
693 '\t\t\t\tName="%s"\n'
694 '\t\t\t\tFilter="">\n' % (key))
695 self.printSources(value, commonprefix)
696 self.file.write('\t\t\t</Filter>\n')
697
698 for key, value in sorteditems:
699 if SCons.Util.is_String(value):
700 file = value
701 if commonprefix:
702 file = os.path.join(commonprefix, value)
703 file = os.path.normpath(file)
704 self.file.write('\t\t\t<File\n'
705 '\t\t\t\tRelativePath="%s">\n'
706 '\t\t\t</File>\n' % (file))
707
708 def PrintSourceFiles(self):
709 categories = {'Source Files': 'cpp;c;cxx;l;y;def;odl;idl;hpj;bat',
710 'Header Files': 'h;hpp;hxx;hm;inl',
711 'Local Headers': 'h;hpp;hxx;hm;inl',
712 'Resource Files': 'r;rc;ico;cur;bmp;dlg;rc2;rct;bin;cnt;rt f;gif;jpg;jpeg;jpe',
713 'Other Files': ''}
714
715 self.file.write('\t<Files>\n')
716
717 cats = sorted([k for k in categories.keys() if self.sources[k]],
718 key=lambda a: a.lower())
719 for kind in cats:
720 if len(cats) > 1:
721 self.file.write('\t\t<Filter\n'
722 '\t\t\tName="%s"\n'
723 '\t\t\tFilter="%s">\n' % (kind, categories[kind] ))
724
725 sources = self.sources[kind]
726
727 # First remove any common prefix
728 commonprefix = None
729 if len(sources) > 1:
730 s = list(map(os.path.normpath, sources))
731 # take the dirname because the prefix may include parts
732 # of the filenames (e.g. if you have 'dir\abcd' and
733 # 'dir\acde' then the cp will be 'dir\a' )
734 cp = os.path.dirname( os.path.commonprefix(s) )
735 if cp and s[0][len(cp)] == os.sep:
736 # +1 because the filename starts after the separator
737 sources = [s[len(cp)+1:] for s in sources]
738 commonprefix = cp
739 elif len(sources) == 1:
740 commonprefix = os.path.dirname( sources[0] )
741 sources[0] = os.path.basename( sources[0] )
742
743 hierarchy = makeHierarchy(sources)
744 self.printSources(hierarchy, commonprefix=commonprefix)
745
746 if len(cats)>1:
747 self.file.write('\t\t</Filter>\n')
748
749 # add the SConscript file outside of the groups
750 self.file.write('\t\t<File\n'
751 '\t\t\tRelativePath="%s">\n'
752 '\t\t</File>\n' % str(self.sconscript))
753
754 self.file.write('\t</Files>\n'
755 '\t<Globals>\n'
756 '\t</Globals>\n')
757
758 def Parse(self):
759 try:
760 dspfile = open(self.dspabs,'r')
761 except IOError:
762 return # doesn't exist yet, so can't add anything to configs.
763
764 line = dspfile.readline()
765 while line:
766 if line.find('<!-- SCons Data:') > -1:
767 break
768 line = dspfile.readline()
769
770 line = dspfile.readline()
771 datas = line
772 while line and line != '\n':
773 line = dspfile.readline()
774 datas = datas + line
775
776 # OK, we've found our little pickled cache of data.
777 try:
778 datas = base64.decodestring(datas)
779 data = pickle.loads(datas)
780 except KeyboardInterrupt:
781 raise
782 except:
783 return # unable to unpickle any data for some reason
784
785 self.configs.update(data)
786
787 data = None
788 line = dspfile.readline()
789 datas = line
790 while line and line != '\n':
791 line = dspfile.readline()
792 datas = datas + line
793
794 # OK, we've found our little pickled cache of data.
795 try:
796 datas = base64.decodestring(datas)
797 data = pickle.loads(datas)
798 except KeyboardInterrupt:
799 raise
800 except:
801 return # unable to unpickle any data for some reason
802
803 self.sources.update(data)
804
805 def Build(self):
806 try:
807 self.file = open(self.dspabs,'w')
808 except IOError, detail:
809 raise SCons.Errors.InternalError('Unable to open "' + self.dspabs + '" for writing:' + str(detail))
810 else:
811 self.PrintHeader()
812 self.PrintProject()
813 self.file.close()
814
815 class _DSWGenerator(object):
816 """ Base class for DSW generators """
817 def __init__(self, dswfile, source, env):
818 self.dswfile = os.path.normpath(str(dswfile))
819 self.env = env
820
821 if 'projects' not in env:
822 raise SCons.Errors.UserError("You must specify a 'projects' argument to create an MSVSSolution.")
823 projects = env['projects']
824 if not SCons.Util.is_List(projects):
825 raise SCons.Errors.InternalError("The 'projects' argument must be a list of nodes.")
826 projects = SCons.Util.flatten(projects)
827 if len(projects) < 1:
828 raise SCons.Errors.UserError("You must specify at least one project to create an MSVSSolution.")
829 self.dspfiles = list(map(str, projects))
830
831 if 'name' in self.env:
832 self.name = self.env['name']
833 else:
834 self.name = os.path.basename(SCons.Util.splitext(self.dswfile)[0])
835 self.name = self.env.subst(self.name)
836
837 def Build(self):
838 pass
839
840 class _GenerateV7DSW(_DSWGenerator):
841 """Generates a Solution file for MSVS .NET"""
842 def __init__(self, dswfile, source, env):
843 _DSWGenerator.__init__(self, dswfile, source, env)
844
845 self.file = None
846 self.version = self.env['MSVS_VERSION']
847 self.version_num, self.suite = msvs_parse_version(self.version)
848 self.versionstr = '7.00'
849 if self.version_num >= 8.0:
850 self.versionstr = '9.00'
851 elif self.version_num >= 7.1:
852 self.versionstr = '8.00'
853 if self.version_num >= 8.0:
854 self.versionstr = '9.00'
855
856 if 'slnguid' in env and env['slnguid']:
857 self.slnguid = env['slnguid']
858 else:
859 self.slnguid = _generateGUID(dswfile, self.name)
860
861 self.configs = {}
862
863 self.nokeep = 0
864 if 'nokeep' in env and env['variant'] != 0:
865 self.nokeep = 1
866
867 if self.nokeep == 0 and os.path.exists(self.dswfile):
868 self.Parse()
869
870 def AddConfig(self, variant, dswfile=dswfile):
871 config = Config()
872
873 match = re.match('(.*)\|(.*)', variant)
874 if match:
875 config.variant = match.group(1)
876 config.platform = match.group(2)
877 else:
878 config.variant = variant
879 config.platform = 'Win32'
880
881 self.configs[variant] = config
882 print "Adding '" + self.name + ' - ' + config.variant + '|' + config .platform + "' to '" + str(dswfile) + "'"
883
884 if 'variant' not in env:
885 raise SCons.Errors.InternalError("You must specify a 'variant' argum ent (i.e. 'Debug' or " +\
886 "'Release') to create an MSVS Solution File.")
887 elif SCons.Util.is_String(env['variant']):
888 AddConfig(self, env['variant'])
889 elif SCons.Util.is_List(env['variant']):
890 for variant in env['variant']:
891 AddConfig(self, variant)
892
893 self.platforms = []
894 for key in self.configs.keys():
895 platform = self.configs[key].platform
896 if not platform in self.platforms:
897 self.platforms.append(platform)
898
899 def Parse(self):
900 try:
901 dswfile = open(self.dswfile,'r')
902 except IOError:
903 return # doesn't exist yet, so can't add anything to configs.
904
905 line = dswfile.readline()
906 while line:
907 if line[:9] == "EndGlobal":
908 break
909 line = dswfile.readline()
910
911 line = dswfile.readline()
912 datas = line
913 while line:
914 line = dswfile.readline()
915 datas = datas + line
916
917 # OK, we've found our little pickled cache of data.
918 try:
919 datas = base64.decodestring(datas)
920 data = pickle.loads(datas)
921 except KeyboardInterrupt:
922 raise
923 except:
924 return # unable to unpickle any data for some reason
925
926 self.configs.update(data)
927
928 def PrintSolution(self):
929 """Writes a solution file"""
930 self.file.write('Microsoft Visual Studio Solution File, Format Version % s\n' % self.versionstr )
931 if self.version_num >= 8.0:
932 self.file.write('# Visual Studio 2005\n')
933 for p in self.dspfiles:
934 name = os.path.basename(p)
935 base, suffix = SCons.Util.splitext(name)
936 if suffix == '.vcproj':
937 name = base
938 guid = _generateGUID(p, '')
939 self.file.write('Project("%s") = "%s", "%s", "%s"\n'
940 % ( external_makefile_guid, name, p, guid ) )
941 if self.version_num >= 7.1 and self.version_num < 8.0:
942 self.file.write('\tProjectSection(ProjectDependencies) = postPro ject\n'
943 '\tEndProjectSection\n')
944 self.file.write('EndProject\n')
945
946 self.file.write('Global\n')
947
948 env = self.env
949 if 'MSVS_SCC_PROVIDER' in env:
950 dspfile_base = os.path.basename(self.dspfile)
951 slnguid = self.slnguid
952 scc_provider = env.get('MSVS_SCC_PROVIDER', '')
953 scc_provider = scc_provider.replace(' ', r'\u0020')
954 scc_project_name = env.get('MSVS_SCC_PROJECT_NAME', '')
955 # scc_aux_path = env.get('MSVS_SCC_AUX_PATH', '')
956 scc_local_path = env.get('MSVS_SCC_LOCAL_PATH', '')
957 scc_project_base_path = env.get('MSVS_SCC_PROJECT_BASE_PATH', '')
958 # project_guid = env.get('MSVS_PROJECT_GUID', '')
959
960 self.file.write('\tGlobalSection(SourceCodeControl) = preSolution\n'
961 '\t\tSccNumberOfProjects = 2\n'
962 '\t\tSccProjectUniqueName0 = %(dspfile_base)s\n'
963 '\t\tSccLocalPath0 = %(scc_local_path)s\n'
964 '\t\tCanCheckoutShared = true\n'
965 '\t\tSccProjectFilePathRelativizedFromConnection0 = %(scc_project_base_path)s\n'
966 '\t\tSccProjectName1 = %(scc_project_name)s\n'
967 '\t\tSccLocalPath1 = %(scc_local_path)s\n'
968 '\t\tSccProvider1 = %(scc_provider)s\n'
969 '\t\tCanCheckoutShared = true\n'
970 '\t\tSccProjectFilePathRelativizedFromConnection1 = %(scc_project_base_path)s\n'
971 '\t\tSolutionUniqueID = %(slnguid)s\n'
972 '\tEndGlobalSection\n' % locals())
973
974 if self.version_num >= 8.0:
975 self.file.write('\tGlobalSection(SolutionConfigurationPlatforms) = p reSolution\n')
976 else:
977 self.file.write('\tGlobalSection(SolutionConfiguration) = preSolutio n\n')
978
979 confkeys = sorted(self.configs.keys())
980 cnt = 0
981 for name in confkeys:
982 variant = self.configs[name].variant
983 platform = self.configs[name].platform
984 if self.version_num >= 8.0:
985 self.file.write('\t\t%s|%s = %s|%s\n' % (variant, platform, vari ant, platform))
986 else:
987 self.file.write('\t\tConfigName.%d = %s\n' % (cnt, variant))
988 cnt = cnt + 1
989 self.file.write('\tEndGlobalSection\n')
990 if self.version_num < 7.1:
991 self.file.write('\tGlobalSection(ProjectDependencies) = postSolution \n'
992 '\tEndGlobalSection\n')
993 if self.version_num >= 8.0:
994 self.file.write('\tGlobalSection(ProjectConfigurationPlatforms) = po stSolution\n')
995 else:
996 self.file.write('\tGlobalSection(ProjectConfiguration) = postSolutio n\n')
997
998 for name in confkeys:
999 variant = self.configs[name].variant
1000 platform = self.configs[name].platform
1001 if self.version_num >= 8.0:
1002 for p in self.dspfiles:
1003 guid = _generateGUID(p, '')
1004 self.file.write('\t\t%s.%s|%s.ActiveCfg = %s|%s\n'
1005 '\t\t%s.%s|%s.Build.0 = %s|%s\n' % (guid,va riant,platform,variant,platform,guid,variant,platform,variant,platform))
1006 else:
1007 for p in self.dspfiles:
1008 guid = _generateGUID(p, '')
1009 self.file.write('\t\t%s.%s.ActiveCfg = %s|%s\n'
1010 '\t\t%s.%s.Build.0 = %s|%s\n' %(guid,varian t,variant,platform,guid,variant,variant,platform))
1011
1012 self.file.write('\tEndGlobalSection\n')
1013
1014 if self.version_num >= 8.0:
1015 self.file.write('\tGlobalSection(SolutionProperties) = preSolution\n '
1016 '\t\tHideSolutionNode = FALSE\n'
1017 '\tEndGlobalSection\n')
1018 else:
1019 self.file.write('\tGlobalSection(ExtensibilityGlobals) = postSolutio n\n'
1020 '\tEndGlobalSection\n'
1021 '\tGlobalSection(ExtensibilityAddIns) = postSolution \n'
1022 '\tEndGlobalSection\n')
1023 self.file.write('EndGlobal\n')
1024 if self.nokeep == 0:
1025 pdata = pickle.dumps(self.configs,1)
1026 pdata = base64.encodestring(pdata)
1027 self.file.write(pdata + '\n')
1028
1029 def Build(self):
1030 try:
1031 self.file = open(self.dswfile,'w')
1032 except IOError, detail:
1033 raise SCons.Errors.InternalError('Unable to open "' + self.dswfile + '" for writing:' + str(detail))
1034 else:
1035 self.PrintSolution()
1036 self.file.close()
1037
1038 V6DSWHeader = """\
1039 Microsoft Developer Studio Workspace File, Format Version 6.00
1040 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
1041
1042 ###############################################################################
1043
1044 Project: "%(name)s"="%(dspfile)s" - Package Owner=<4>
1045
1046 Package=<5>
1047 {{{
1048 }}}
1049
1050 Package=<4>
1051 {{{
1052 }}}
1053
1054 ###############################################################################
1055
1056 Global:
1057
1058 Package=<5>
1059 {{{
1060 }}}
1061
1062 Package=<3>
1063 {{{
1064 }}}
1065
1066 ###############################################################################
1067 """
1068
1069 class _GenerateV6DSW(_DSWGenerator):
1070 """Generates a Workspace file for MSVS 6.0"""
1071
1072 def PrintWorkspace(self):
1073 """ writes a DSW file """
1074 name = self.name
1075 dspfile = self.dspfiles[0]
1076 self.file.write(V6DSWHeader % locals())
1077
1078 def Build(self):
1079 try:
1080 self.file = open(self.dswfile,'w')
1081 except IOError, detail:
1082 raise SCons.Errors.InternalError('Unable to open "' + self.dswfile + '" for writing:' + str(detail))
1083 else:
1084 self.PrintWorkspace()
1085 self.file.close()
1086
1087
1088 def GenerateDSP(dspfile, source, env):
1089 """Generates a Project file based on the version of MSVS that is being used" ""
1090
1091 version_num = 6.0
1092 if 'MSVS_VERSION' in env:
1093 version_num, suite = msvs_parse_version(env['MSVS_VERSION'])
1094 if version_num >= 7.0:
1095 g = _GenerateV7DSP(dspfile, source, env)
1096 g.Build()
1097 else:
1098 g = _GenerateV6DSP(dspfile, source, env)
1099 g.Build()
1100
1101 def GenerateDSW(dswfile, source, env):
1102 """Generates a Solution/Workspace file based on the version of MSVS that is being used"""
1103
1104 version_num = 6.0
1105 if 'MSVS_VERSION' in env:
1106 version_num, suite = msvs_parse_version(env['MSVS_VERSION'])
1107 if version_num >= 7.0:
1108 g = _GenerateV7DSW(dswfile, source, env)
1109 g.Build()
1110 else:
1111 g = _GenerateV6DSW(dswfile, source, env)
1112 g.Build()
1113
1114
1115 ##############################################################################
1116 # Above here are the classes and functions for generation of
1117 # DSP/DSW/SLN/VCPROJ files.
1118 ##############################################################################
1119
1120 def GetMSVSProjectSuffix(target, source, env, for_signature):
1121 return env['MSVS']['PROJECTSUFFIX']
1122
1123 def GetMSVSSolutionSuffix(target, source, env, for_signature):
1124 return env['MSVS']['SOLUTIONSUFFIX']
1125
1126 def GenerateProject(target, source, env):
1127 # generate the dsp file, according to the version of MSVS.
1128 builddspfile = target[0]
1129 dspfile = builddspfile.srcnode()
1130
1131 # this detects whether or not we're using a VariantDir
1132 if not dspfile is builddspfile:
1133 try:
1134 bdsp = open(str(builddspfile), "w+")
1135 except IOError, detail:
1136 print 'Unable to open "' + str(dspfile) + '" for writing:',detail,'\ n'
1137 raise
1138
1139 bdsp.write("This is just a placeholder file.\nThe real project file is h ere:\n%s\n" % dspfile.get_abspath())
1140
1141 GenerateDSP(dspfile, source, env)
1142
1143 if env.get('auto_build_solution', 1):
1144 builddswfile = target[1]
1145 dswfile = builddswfile.srcnode()
1146
1147 if not dswfile is builddswfile:
1148
1149 try:
1150 bdsw = open(str(builddswfile), "w+")
1151 except IOError, detail:
1152 print 'Unable to open "' + str(dspfile) + '" for writing:',detai l,'\n'
1153 raise
1154
1155 bdsw.write("This is just a placeholder file.\nThe real workspace fil e is here:\n%s\n" % dswfile.get_abspath())
1156
1157 GenerateDSW(dswfile, source, env)
1158
1159 def GenerateSolution(target, source, env):
1160 GenerateDSW(target[0], source, env)
1161
1162 def projectEmitter(target, source, env):
1163 """Sets up the DSP dependencies."""
1164
1165 # todo: Not sure what sets source to what user has passed as target,
1166 # but this is what happens. When that is fixed, we also won't have
1167 # to make the user always append env['MSVSPROJECTSUFFIX'] to target.
1168 if source[0] == target[0]:
1169 source = []
1170
1171 # make sure the suffix is correct for the version of MSVS we're running.
1172 (base, suff) = SCons.Util.splitext(str(target[0]))
1173 suff = env.subst('$MSVSPROJECTSUFFIX')
1174 target[0] = base + suff
1175
1176 if not source:
1177 source = 'prj_inputs:'
1178 source = source + env.subst('$MSVSSCONSCOM', 1)
1179 source = source + env.subst('$MSVSENCODING', 1)
1180
1181 if 'buildtarget' in env and env['buildtarget'] != None:
1182 if SCons.Util.is_String(env['buildtarget']):
1183 source = source + ' "%s"' % env['buildtarget']
1184 elif SCons.Util.is_List(env['buildtarget']):
1185 for bt in env['buildtarget']:
1186 if SCons.Util.is_String(bt):
1187 source = source + ' "%s"' % bt
1188 else:
1189 try: source = source + ' "%s"' % bt.get_abspath()
1190 except AttributeError: raise SCons.Errors.InternalError( "buildtarget can be a string, a node, a list of strings or nodes, or None")
1191 else:
1192 try: source = source + ' "%s"' % env['buildtarget'].get_abspath( )
1193 except AttributeError: raise SCons.Errors.InternalError("buildta rget can be a string, a node, a list of strings or nodes, or None")
1194
1195 if 'outdir' in env and env['outdir'] != None:
1196 if SCons.Util.is_String(env['outdir']):
1197 source = source + ' "%s"' % env['outdir']
1198 elif SCons.Util.is_List(env['outdir']):
1199 for s in env['outdir']:
1200 if SCons.Util.is_String(s):
1201 source = source + ' "%s"' % s
1202 else:
1203 try: source = source + ' "%s"' % s.get_abspath()
1204 except AttributeError: raise SCons.Errors.InternalError( "outdir can be a string, a node, a list of strings or nodes, or None")
1205 else:
1206 try: source = source + ' "%s"' % env['outdir'].get_abspath()
1207 except AttributeError: raise SCons.Errors.InternalError("outdir can be a string, a node, a list of strings or nodes, or None")
1208
1209 if 'name' in env:
1210 if SCons.Util.is_String(env['name']):
1211 source = source + ' "%s"' % env['name']
1212 else:
1213 raise SCons.Errors.InternalError("name must be a string")
1214
1215 if 'variant' in env:
1216 if SCons.Util.is_String(env['variant']):
1217 source = source + ' "%s"' % env['variant']
1218 elif SCons.Util.is_List(env['variant']):
1219 for variant in env['variant']:
1220 if SCons.Util.is_String(variant):
1221 source = source + ' "%s"' % variant
1222 else:
1223 raise SCons.Errors.InternalError("name must be a string or a list of strings")
1224 else:
1225 raise SCons.Errors.InternalError("variant must be a string or a list of strings")
1226 else:
1227 raise SCons.Errors.InternalError("variant must be specified")
1228
1229 for s in _DSPGenerator.srcargs:
1230 if s in env:
1231 if SCons.Util.is_String(env[s]):
1232 source = source + ' "%s' % env[s]
1233 elif SCons.Util.is_List(env[s]):
1234 for t in env[s]:
1235 if SCons.Util.is_String(t):
1236 source = source + ' "%s"' % t
1237 else:
1238 raise SCons.Errors.InternalError(s + " must be a str ing or a list of strings")
1239 else:
1240 raise SCons.Errors.InternalError(s + " must be a string or a list of strings")
1241
1242 source = source + ' "%s"' % str(target[0])
1243 source = [SCons.Node.Python.Value(source)]
1244
1245 targetlist = [target[0]]
1246 sourcelist = source
1247
1248 if env.get('auto_build_solution', 1):
1249 env['projects'] = targetlist
1250 t, s = solutionEmitter(target, target, env)
1251 targetlist = targetlist + t
1252
1253 return (targetlist, sourcelist)
1254
1255 def solutionEmitter(target, source, env):
1256 """Sets up the DSW dependencies."""
1257
1258 # todo: Not sure what sets source to what user has passed as target,
1259 # but this is what happens. When that is fixed, we also won't have
1260 # to make the user always append env['MSVSSOLUTIONSUFFIX'] to target.
1261 if source[0] == target[0]:
1262 source = []
1263
1264 # make sure the suffix is correct for the version of MSVS we're running.
1265 (base, suff) = SCons.Util.splitext(str(target[0]))
1266 suff = env.subst('$MSVSSOLUTIONSUFFIX')
1267 target[0] = base + suff
1268
1269 if not source:
1270 source = 'sln_inputs:'
1271
1272 if 'name' in env:
1273 if SCons.Util.is_String(env['name']):
1274 source = source + ' "%s"' % env['name']
1275 else:
1276 raise SCons.Errors.InternalError("name must be a string")
1277
1278 if 'variant' in env:
1279 if SCons.Util.is_String(env['variant']):
1280 source = source + ' "%s"' % env['variant']
1281 elif SCons.Util.is_List(env['variant']):
1282 for variant in env['variant']:
1283 if SCons.Util.is_String(variant):
1284 source = source + ' "%s"' % variant
1285 else:
1286 raise SCons.Errors.InternalError("name must be a string or a list of strings")
1287 else:
1288 raise SCons.Errors.InternalError("variant must be a string or a list of strings")
1289 else:
1290 raise SCons.Errors.InternalError("variant must be specified")
1291
1292 if 'slnguid' in env:
1293 if SCons.Util.is_String(env['slnguid']):
1294 source = source + ' "%s"' % env['slnguid']
1295 else:
1296 raise SCons.Errors.InternalError("slnguid must be a string")
1297
1298 if 'projects' in env:
1299 if SCons.Util.is_String(env['projects']):
1300 source = source + ' "%s"' % env['projects']
1301 elif SCons.Util.is_List(env['projects']):
1302 for t in env['projects']:
1303 if SCons.Util.is_String(t):
1304 source = source + ' "%s"' % t
1305
1306 source = source + ' "%s"' % str(target[0])
1307 source = [SCons.Node.Python.Value(source)]
1308
1309 return ([target[0]], source)
1310
1311 projectAction = SCons.Action.Action(GenerateProject, None)
1312
1313 solutionAction = SCons.Action.Action(GenerateSolution, None)
1314
1315 projectBuilder = SCons.Builder.Builder(action = '$MSVSPROJECTCOM',
1316 suffix = '$MSVSPROJECTSUFFIX',
1317 emitter = projectEmitter)
1318
1319 solutionBuilder = SCons.Builder.Builder(action = '$MSVSSOLUTIONCOM',
1320 suffix = '$MSVSSOLUTIONSUFFIX',
1321 emitter = solutionEmitter)
1322
1323 default_MSVS_SConscript = None
1324
1325 def generate(env):
1326 """Add Builders and construction variables for Microsoft Visual
1327 Studio project files to an Environment."""
1328 try:
1329 env['BUILDERS']['MSVSProject']
1330 except KeyError:
1331 env['BUILDERS']['MSVSProject'] = projectBuilder
1332
1333 try:
1334 env['BUILDERS']['MSVSSolution']
1335 except KeyError:
1336 env['BUILDERS']['MSVSSolution'] = solutionBuilder
1337
1338 env['MSVSPROJECTCOM'] = projectAction
1339 env['MSVSSOLUTIONCOM'] = solutionAction
1340
1341 if SCons.Script.call_stack:
1342 # XXX Need to find a way to abstract this; the build engine
1343 # shouldn't depend on anything in SCons.Script.
1344 env['MSVSSCONSCRIPT'] = SCons.Script.call_stack[0].sconscript
1345 else:
1346 global default_MSVS_SConscript
1347 if default_MSVS_SConscript is None:
1348 default_MSVS_SConscript = env.File('SConstruct')
1349 env['MSVSSCONSCRIPT'] = default_MSVS_SConscript
1350
1351 env['MSVSSCONS'] = '"%s" -c "%s"' % (python_executable, getExecScriptMain(en v))
1352 env['MSVSSCONSFLAGS'] = '-C "${MSVSSCONSCRIPT.dir.abspath}" -f ${MSVSSCONSCR IPT.name}'
1353 env['MSVSSCONSCOM'] = '$MSVSSCONS $MSVSSCONSFLAGS'
1354 env['MSVSBUILDCOM'] = '$MSVSSCONSCOM "$MSVSBUILDTARGET"'
1355 env['MSVSREBUILDCOM'] = '$MSVSSCONSCOM "$MSVSBUILDTARGET"'
1356 env['MSVSCLEANCOM'] = '$MSVSSCONSCOM -c "$MSVSBUILDTARGET"'
1357 env['MSVSENCODING'] = 'Windows-1252'
1358
1359 # Set-up ms tools paths for default version
1360 msvc_setup_env_once(env)
1361
1362 if 'MSVS_VERSION' in env:
1363 version_num, suite = msvs_parse_version(env['MSVS_VERSION'])
1364 else:
1365 (version_num, suite) = (7.0, None) # guess at a default
1366 if 'MSVS' not in env:
1367 env['MSVS'] = {}
1368 if (version_num < 7.0):
1369 env['MSVS']['PROJECTSUFFIX'] = '.dsp'
1370 env['MSVS']['SOLUTIONSUFFIX'] = '.dsw'
1371 else:
1372 env['MSVS']['PROJECTSUFFIX'] = '.vcproj'
1373 env['MSVS']['SOLUTIONSUFFIX'] = '.sln'
1374
1375 env['GET_MSVSPROJECTSUFFIX'] = GetMSVSProjectSuffix
1376 env['GET_MSVSSOLUTIONSUFFIX'] = GetMSVSSolutionSuffix
1377 env['MSVSPROJECTSUFFIX'] = '${GET_MSVSPROJECTSUFFIX}'
1378 env['MSVSSOLUTIONSUFFIX'] = '${GET_MSVSSOLUTIONSUFFIX}'
1379 env['SCONS_HOME'] = os.environ.get('SCONS_HOME')
1380
1381 def exists(env):
1382 return msvc_exists()
1383
1384 # Local Variables:
1385 # tab-width:4
1386 # indent-tabs-mode:nil
1387 # End:
1388 # vim: set expandtab tabstop=4 shiftwidth=4:
OLDNEW
« no previous file with comments | « scons-2.0.1/engine/SCons/Tool/msvc.py ('k') | scons-2.0.1/engine/SCons/Tool/mwcc.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698