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

Side by Side Diff: site_scons/site_tools/_Node_MSVS.py

Issue 17436: Generation of net .vcproj and .sln files.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 11 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 | « net/tools/tld_cleanup/tld_cleanup.scons ('k') | site_scons/site_tools/chromium_builders.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # 1 #
2 # __COPYRIGHT__ 2 # __COPYRIGHT__
3 # 3 #
4 # Permission is hereby granted, free of charge, to any person obtaining 4 # Permission is hereby granted, free of charge, to any person obtaining
5 # a copy of this software and associated documentation files (the 5 # a copy of this software and associated documentation files (the
6 # "Software"), to deal in the Software without restriction, including 6 # "Software"), to deal in the Software without restriction, including
7 # without limitation the rights to use, copy, modify, merge, publish, 7 # without limitation the rights to use, copy, modify, merge, publish,
8 # distribute, sublicense, and/or sell copies of the Software, and to 8 # distribute, sublicense, and/or sell copies of the Software, and to
9 # permit persons to whom the Software is furnished to do so, subject to 9 # permit persons to whom the Software is furnished to do so, subject to
10 # the following conditions: 10 # the following conditions:
(...skipping 21 matching lines...) Expand all
32 import os 32 import os
33 import random 33 import random
34 import re 34 import re
35 import UserList 35 import UserList
36 import xml.dom 36 import xml.dom
37 import xml.dom.minidom 37 import xml.dom.minidom
38 38
39 import SCons.Node.FS 39 import SCons.Node.FS
40 import SCons.Script 40 import SCons.Script
41 41
42 from SCons.Debug import Trace
43 TODO = 0
42 44
43 # Initialize random number generator 45 # Initialize random number generator
44 random.seed() 46 random.seed()
45 47
46 48
47 #------------------------------------------------------------------------------ 49 #------------------------------------------------------------------------------
48 # Entry point for supplying a fixed map of GUIDs for testing. 50 # Entry point for supplying a fixed map of GUIDs for testing.
49 51
50 GUIDMap = {} 52 GUIDMap = {}
51 53
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 def get_msvs_path(self, sln): 259 def get_msvs_path(self, sln):
258 return self.msvs_name 260 return self.msvs_name
259 261
260 def MSVSFolder(env, item, *args, **kw): 262 def MSVSFolder(env, item, *args, **kw):
261 return LookupCreate(_MSVSFolder, item, *args, **kw) 263 return LookupCreate(_MSVSFolder, item, *args, **kw)
262 264
263 #------------------------------------------------------------------------------ 265 #------------------------------------------------------------------------------
264 266
265 class MSVSConfig(object): 267 class MSVSConfig(object):
266 """Visual Studio configuration.""" 268 """Visual Studio configuration."""
267 def __init__(self, Name, config_type, tools=[], **attrs): 269 def __init__(self, Name, config_type, tools=None, **attrs):
268 """Initializes the configuration. 270 """Initializes the configuration.
269 271
270 Args: 272 Args:
271 **attrs: Configuration attributes. 273 **attrs: Configuration attributes.
272 """ 274 """
273 # Special handling for attributes that we want to make more 275 # Special handling for attributes that we want to make more
274 # convenient for the user. 276 # convenient for the user.
275 ips = attrs.get('InheritedPropertySheets') 277 ips = attrs.get('InheritedPropertySheets')
276 if ips: 278 if ips:
277 if isinstance(ips, list): 279 if isinstance(ips, list):
278 ips = ';'.join(ips) 280 ips = ';'.join(ips)
279 attrs['InheritedPropertySheets'] = ips.replace('/', '\\') 281 attrs['InheritedPropertySheets'] = ips.replace('/', '\\')
280 282
281 tools = tools or []
282 if not SCons.Util.is_List(tools):
283 tools = [tools]
284 tool_objects = []
285 for t in tools:
286 if not isinstance(t, MSVSTool):
287 t = MSVSTool(t)
288 tool_objects.append(t)
289
290 self.Name = Name 283 self.Name = Name
291 self.config_type = config_type 284 self.config_type = config_type
292 self.tools = tool_objects 285 self.tools = tools
293 self.attrs = attrs 286 self.attrs = attrs
294 287
295 def CreateElement(self, doc): 288 def CreateElement(self, doc, project):
296 """Creates an element for the configuration. 289 """Creates an element for the configuration.
297 290
298 Args: 291 Args:
299 doc: xml.dom.Document object to use for node creation. 292 doc: xml.dom.Document object to use for node creation.
300 293
301 Returns: 294 Returns:
302 A new xml.dom.Element for the configuration. 295 A new xml.dom.Element for the configuration.
303 """ 296 """
304 node = doc.createElement(self.config_type) 297 node = doc.createElement(self.config_type)
305 node.setAttribute('Name', self.Name) 298 node.setAttribute('Name', self.Name)
306 for k, v in self.attrs.items(): 299 for k, v in self.attrs.items():
307 node.setAttribute(k, v) 300 node.setAttribute(k, v)
308 for t in self.tools: 301
302 tools = self.tools
303 if tools is None:
304 tools = project.tools or []
305 if not SCons.Util.is_List(tools):
306 tools = [tools]
307 tool_objects = []
308 for t in tools:
309 if not isinstance(t, MSVSTool):
310 t = MSVSTool(t)
311 tool_objects.append(t)
312 for t in tool_objects:
309 node.appendChild(t.CreateElement(doc)) 313 node.appendChild(t.CreateElement(doc))
314
310 return node 315 return node
311 316
312 317
313 class MSVSFileListBase(FileList): 318 class MSVSFileListBase(FileList):
314 """Base class for a file list in a Visual Studio project file.""" 319 """Base class for a file list in a Visual Studio project file."""
315 320
316 def CreateElement(self, doc, node_func=lambda x: x): 321 def CreateElement(self, doc, node_func=lambda x: x):
317 """Creates an element for an MSVSFileListBase subclass. 322 """Creates an element for an MSVSFileListBase subclass.
318 323
319 Args: 324 Args:
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
391 396
392 Returns: 397 Returns:
393 A new xml.dom.Element for the tool. 398 A new xml.dom.Element for the tool.
394 """ 399 """
395 node = doc.createElement('Tool') 400 node = doc.createElement('Tool')
396 node.setAttribute('Name', self.Name) 401 node.setAttribute('Name', self.Name)
397 for k, v in self.attrs.items(): 402 for k, v in self.attrs.items():
398 node.setAttribute(k, v) 403 node.setAttribute(k, v)
399 return node 404 return node
400 405
406 def _format(self):
407 """Formats a tool specification for debug printing"""
408 xml_impl = xml.dom.getDOMImplementation()
409 doc = xml_impl.createDocument(None, 'VisualStudioProject', None)
410 return self.CreateElement(doc).toprettyxml()
411
412 def diff(self, other):
413 for key, value in self.attrs.items():
414 if other.attrs[key] == value:
415 del self.attrs[key]
416
401 417
402 class MSVSToolFile(object): 418 class MSVSToolFile(object):
403 """Visual Studio tool file specification.""" 419 """Visual Studio tool file specification."""
404 420
405 def __init__(self, node, **attrs): 421 def __init__(self, node, **attrs):
406 """Initializes the tool. 422 """Initializes the tool.
407 423
408 Args: 424 Args:
409 node: Node for the Tool File 425 node: Node for the Tool File
410 **attrs: Tool File attributes. 426 **attrs: Tool File attributes.
(...skipping 11 matching lines...) Expand all
422 def MSVSAction(target, source, env): 438 def MSVSAction(target, source, env):
423 target[0].Write(env) 439 target[0].Write(env)
424 440
425 MSVSProjectAction = SCons.Script.Action(MSVSAction, 441 MSVSProjectAction = SCons.Script.Action(MSVSAction,
426 "Generating Visual Studio project `$TARG ET' ...") 442 "Generating Visual Studio project `$TARG ET' ...")
427 443
428 class _MSVSProject(SCons.Node.FS.File): 444 class _MSVSProject(SCons.Node.FS.File):
429 """Visual Studio project.""" 445 """Visual Studio project."""
430 446
431 entry_type_guid = '{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}' 447 entry_type_guid = '{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}'
448 initialized = False
432 449
433 def initialize(self, env, path, name = None, 450 def initialize(self, env, path, name = None,
434 dependencies = None, 451 dependencies = None,
435 guid = None, 452 guid = None,
436 buildtargets = [], 453 buildtargets = [],
437 files = [], 454 files = [],
438 root_namespace = None, 455 root_namespace = None,
439 relative_path_prefix = '', 456 relative_path_prefix = '',
440 tools = None, 457 tools = None,
441 configurations = None): 458 configurations = None,
459 **attrs):
442 """Initializes the project. 460 """Initializes the project.
443 461
444 Args: 462 Args:
445 path: Relative path to project file. 463 path: Relative path to project file.
446 name: Name of project. If None, the name will be the same as the base 464 name: Name of project. If None, the name will be the same as the base
447 name of the project file. 465 name of the project file.
448 dependencies: List of other Project objects this project is dependent 466 dependencies: List of other Project objects this project is dependent
449 upon, if not None. 467 upon, if not None.
450 guid: GUID to use for project, if not None. 468 guid: GUID to use for project, if not None.
451 buildtargets: List of target(s) being built by this project. 469 buildtargets: List of target(s) being built by this project.
452 files: List of source files for the project. This will be 470 files: List of source files for the project. This will be
453 supplemented by any source files of buildtargets. 471 supplemented by any source files of buildtargets.
454 root_namespace: The value of the RootNamespace attribute of the 472 root_namespace: The value of the RootNamespace attribute of the
455 project, if not None. The default is to use the same 473 project, if not None. The default is to use the same
456 string as the name. 474 string as the name.
457 relative_path_prefix: A prefix to be appended to the beginning of 475 relative_path_prefix: A prefix to be appended to the beginning of
458 every file name in the list. The canonical use is to specify 476 every file name in the list. The canonical use is to specify
459 './' to make files explicitly relative to the local directory. 477 './' to make files explicitly relative to the local directory.
460 tools: A list of MSVSTool objects or strings representing 478 tools: A list of MSVSTool objects or strings representing
461 tools to be used to build this project. This will be used 479 tools to be used to build this project. This will be used
462 for any configurations that don't provide their own 480 for any configurations that don't provide their own
463 per-configuration tool list. 481 per-configuration tool list.
464 configurations: A list of MSVSConfig objects representing 482 configurations: A list of MSVSConfig objects representing
465 configurations built by this project. 483 configurations built by this project.
466 """ 484 """
467 self.msvs_path = path
468 self.msvs_node = env.File(path)
469 if name is None: 485 if name is None:
470 if buildtargets: 486 if buildtargets:
471 name = os.path.splitext(buildtargets[0].name)[0] 487 name = os.path.splitext(buildtargets[0].name)[0]
472 else: 488 else:
473 name = os.path.splitext(os.path.basename(path))[0] 489 name = os.path.splitext(os.path.basename(path))[0]
490 if not root_namespace:
491 root_namespace or name
492
493 if self.initialized:
494 # TODO(sgk): fill in
495 if self.msvs_name != name:
496 pass
497 if self.root_namespace != root_namespace:
498 pass
499 if self.relative_path_prefix != relative_path_prefix:
500 pass
501 if self.guid != guid:
502 pass
503 #if self.env != env:
504 # pass
505 else:
506 self.buildtargets = []
507 self.configurations = []
508 self.dependencies = []
509 self.file_configurations = {}
510 self.files = MSVSFiles([])
511 self.tool_files = []
512 self.file_lists = []
513 self.initialized = True
514
515 self.attrs = attrs
516 self.env = env
517 self.guid = guid
474 self.msvs_name = name 518 self.msvs_name = name
519 self.msvs_path = path
520 self.relative_path_prefix = relative_path_prefix
475 self.root_namespace = root_namespace or self.msvs_name 521 self.root_namespace = root_namespace or self.msvs_name
476 self.buildtargets = buildtargets
477 self.relative_path_prefix = relative_path_prefix
478 self.tools = tools 522 self.tools = tools
479 523
480 self.env = env 524 self.buildtargets.extend(buildtargets)
481 self.guid = guid 525 self.configurations.extend(configurations or [])
526 self.dependencies.extend(list(dependencies or []))
527 self.AddFiles(files)
482 528
483 self.dependencies = list(dependencies or []) 529 env.Command(self, [], MSVSProjectAction)
484 self.configurations = list(configurations or [])
485 self.file_configurations = {}
486 self.tool_files = []
487
488 if not isinstance(files, MSVSFiles):
489 files = MSVSFiles(self.args2nodes(files))
490 self.files = files
491
492 env.Command(self, [], MSVSSolutionAction)
493 530
494 def args2nodes(self, entries): 531 def args2nodes(self, entries):
495 result = [] 532 result = []
496 for entry in entries: 533 for entry in entries:
497 if SCons.Util.is_String(entry): 534 if SCons.Util.is_String(entry):
498 entry = self.env.File(entry) 535 entry = self.env.File(entry)
499 result.append(entry) 536 result.append(entry)
500 elif hasattr(entry, 'entries'): 537 elif hasattr(entry, 'entries'):
501 entry.entries = self.args2nodes(entry.entries) 538 entry.entries = self.args2nodes(entry.entries)
502 result.append(entry) 539 result.append(entry)
503 elif isinstance(entry, (list, UserList.UserList)): 540 elif isinstance(entry, (list, UserList.UserList)):
504 result.extend(self.args2nodes(entry)) 541 result.extend(self.args2nodes(entry))
505 elif hasattr(entry, 'sources') and entry.sources: 542 elif hasattr(entry, 'sources') and entry.sources:
506 result.extend(entry.sources) 543 result.extend(entry.sources)
507 else: 544 else:
508 result.append(entry) 545 result.append(entry.srcnode())
509 return result 546 return result
510 547
511 def FindFile(self, node): 548 def FindFile(self, node):
512 try: 549 try:
513 flat_file_dict = self.flat_file_dict 550 flat_file_dict = self.flat_file_dict
514 except AttributeError: 551 except AttributeError:
515 flat_file_dict = {} 552 flat_file_dict = {}
516 file_list = self.files[:] 553 file_list = self.files[:]
517 while file_list: 554 while file_list:
518 entry = file_list.pop(0) 555 entry = file_list.pop(0)
519 if not isinstance(entry, (list, UserList.UserList)): 556 if not isinstance(entry, (list, UserList.UserList)):
520 entry = [entry] 557 entry = [entry]
521 for f in entry: 558 for f in entry:
522 if hasattr(f, 'entries'): 559 if hasattr(f, 'entries'):
523 file_list.extend(f.entries) 560 file_list.extend(f.entries)
524 else: 561 else:
525 flat_file_dict[f] = True 562 flat_file_dict[f] = True
563 flat_file_dict[f.srcnode()] = True
526 if hasattr(f, 'sources'): 564 if hasattr(f, 'sources'):
527 for s in f.sources: 565 for s in f.sources:
528 flat_file_dict[s] = True 566 flat_file_dict[s] = True
567 flat_file_dict[s.srcnode()] = True
529 self.flat_file_dict = flat_file_dict 568 self.flat_file_dict = flat_file_dict
530 569
531 return flat_file_dict.get(node) 570 return flat_file_dict.get(node)
532 571
533 def get_guid(self): 572 def get_guid(self):
534 if self.guid is None: 573 if self.guid is None:
535 guid = GUIDMap.get(self.msvs_path) 574 guid = GUIDMap.get(self.msvs_path)
536 if not guid: 575 if not guid:
537 # Set GUID from path 576 # Set GUID from path
538 # TODO(rspangler): This is fragile. 577 # TODO(rspangler): This is fragile.
539 # 1. We can't just use the project filename sans path, since there 578 # 1. We can't just use the project filename sans path, since there
540 # could be multiple projects with the same base name (for example, 579 # could be multiple projects with the same base name (for example,
541 # foo/unittest.vcproj and bar/unittest.vcproj). 580 # foo/unittest.vcproj and bar/unittest.vcproj).
542 # 2. The path needs to be relative to $SOURCE_ROOT, so that the project 581 # 2. The path needs to be relative to $SOURCE_ROOT, so that the project
543 # GUID is the same whether it's included from base/base.sln or 582 # GUID is the same whether it's included from base/base.sln or
544 # foo/bar/baz/baz.sln. 583 # foo/bar/baz/baz.sln.
545 # 3. The GUID needs to be the same each time this builder is invoked, 584 # 3. The GUID needs to be the same each time this builder is invoked,
546 # so that we don't need to rebuild the solution when the 585 # so that we don't need to rebuild the solution when the
547 # project changes. 586 # project changes.
548 # 4. We should be able to handle pre-built project files by reading the 587 # 4. We should be able to handle pre-built project files by reading the
549 # GUID from the files. 588 # GUID from the files.
550 guid = MakeGuid(self.msvs_path) 589 guid = MakeGuid(self.msvs_path)
551 self.guid = guid 590 self.guid = guid
552 return self.guid 591 return self.guid
553 592
554 def get_msvs_path(self, sln): 593 def get_msvs_path(self, sln):
555 return sln.rel_path(self).replace('/', '\\') 594 return sln.rel_path(self).replace('/', '\\')
556 595
557 def get_rel_path(self, node): 596 def get_rel_path(self, node):
558 result = self.relative_path_prefix + self.msvs_node.rel_path(node) 597 result = self.relative_path_prefix + self.rel_path(node)
559 return result.replace('/', '\\') 598 return result.replace('/', '\\')
560 599
561 def AddConfig(self, Name, tools=None, **attrs): 600 def AddConfig(self, Name, tools=None, **attrs):
562 """Adds a configuration to the parent node. 601 """Adds a configuration to the parent node.
563 602
564 Args: 603 Args:
565 Name: The name of the configuration. 604 Name: The name of the configuration.
566 tools: List of tools (strings or Tool objects); may be None. 605 tools: List of tools (strings or Tool objects); may be None.
567 **attrs: Configuration attributes. 606 **attrs: Configuration attributes.
568 """ 607 """
569 if tools is None: 608 if tools is None:
570 # No tool list specifically for this configuration, 609 # No tool list specifically for this configuration,
571 # use the Project's as a default. 610 # use the Project's as a default.
572 tools = self.tools 611 tools = self.tools
612 if not attrs.has_key('ConfigurationType'):
613 # No ConfigurationType specifically for this configuration,
614 # use the Project's as a default.
615 try:
616 attrs['ConfigurationType'] = self.attrs['ConfigurationType']
617 except KeyError:
618 pass
619 if attrs.has_key('InheritedPropertySheets'):
620 ips = attrs['InheritedPropertySheets']
621 attrs['InheritedPropertySheets'] = self.env.subst(ips)
573 c = MSVSConfig(Name, 'Configuration', tools=tools, **attrs) 622 c = MSVSConfig(Name, 'Configuration', tools=tools, **attrs)
574 self.configurations.append(c) 623 self.configurations.append(c)
575 624
576 def AddFiles(self, files): 625 def AddFiles(self, files):
577 """Adds files to the project. 626 """Adds files to the project.
578 627
579 Args: 628 Args:
580 files: A list of Filter objects and/or relative paths to files. 629 files: A list of Filter objects and/or relative paths to files.
581 630
582 This makes a copy of the file/filter tree at the time of this call. If you 631 This makes a copy of the file/filter tree at the time of this call. If you
583 later add files to a Filter object which was passed into a previous call 632 later add files to a Filter object which was passed into a previous call
584 to AddFiles(), it will not be reflected in this project. 633 to AddFiles(), it will not be reflected in this project.
585 """ 634 """
586 # TODO(rspangler) This also doesn't handle adding files to an existing 635 self.file_lists.append(self.args2nodes(files))
587 # filter. That is, it doesn't merge the trees. 636
588 self.files.extend(self.args2nodes(files)) 637 def _FilesToSourceFiles(self, files):
638 file_list = files[:]
639 result = []
640 while file_list:
641 entry = file_list.pop(0)
642 if not isinstance(entry, (list, UserList.UserList)):
643 entry = [entry]
644 for f in entry:
645 if hasattr(f, 'entries'):
646 self._FilesToSourceFiles(f.entries)
647 result.append(f)
648 else:
649 if f.sources:
650 flist = f.sources
651 else:
652 flist = [f]
653 for x in flist:
654 result.append(x.srcnode())
655 files[:] = result
656
657 def _MergeFiles(self, dest_list, src_list):
658 for f in src_list:
659 if f not in dest_list:
660 dest_list.append(f)
661 continue
662 #if hasattr(f, 'entries'):
663 # self._FilesToSourceFiles(f.entries)
589 664
590 def AddFileConfig(self, path, Name, tools=None, **attrs): 665 def AddFileConfig(self, path, Name, tools=None, **attrs):
591 """Adds a configuration to a file. 666 """Adds a configuration to a file.
592 667
593 Args: 668 Args:
594 path: Relative path to the file. 669 path: Relative path to the file.
595 Name: Name of configuration to add. 670 Name: Name of configuration to add.
596 tools: List of tools (strings or MSVSTool objects); may be None. 671 tools: List of tools (strings or MSVSTool objects); may be None.
597 **attrs: Configuration attributes. 672 **attrs: Configuration attributes.
598 673
599 Raises: 674 Raises:
600 ValueError: Relative path does not match any file added via AddFiles(). 675 ValueError: Relative path does not match any file added via AddFiles().
601 """ 676 """
677 # Store as the VariantDir node, not as the source node.
602 node = self.env.File(path) 678 node = self.env.File(path)
603 if not self.FindFile(node):
604 raise ValueError('AddFileConfig: file "%s" not in project' % path)
605 c = MSVSConfig(Name, 'FileConfiguration', tools=tools, **attrs) 679 c = MSVSConfig(Name, 'FileConfiguration', tools=tools, **attrs)
606 config_list = self.file_configurations.get(node) 680 config_list = self.file_configurations.get(node)
607 if config_list is None: 681 if config_list is None:
608 config_list = [] 682 config_list = []
609 self.file_configurations[node] = config_list 683 self.file_configurations[node] = config_list
610 config_list.append(c) 684 config_list.append(c)
611 685
612 def AddToolFile(self, path): 686 def AddToolFile(self, path):
613 """Adds a tool file to the project. 687 """Adds a tool file to the project.
614 688
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
648 # Add tool files section 722 # Add tool files section
649 tool_files = self.doc.createElement('ToolFiles') 723 tool_files = self.doc.createElement('ToolFiles')
650 root.appendChild(tool_files) 724 root.appendChild(tool_files)
651 for tf in self.tool_files: 725 for tf in self.tool_files:
652 tool_files.appendChild(tf.CreateElement(self.doc, self)) 726 tool_files.appendChild(tf.CreateElement(self.doc, self))
653 727
654 # Add configurations section 728 # Add configurations section
655 configs = self.doc.createElement('Configurations') 729 configs = self.doc.createElement('Configurations')
656 root.appendChild(configs) 730 root.appendChild(configs)
657 for c in self.configurations: 731 for c in self.configurations:
658 configs.appendChild(c.CreateElement(self.doc)) 732 configs.appendChild(c.CreateElement(self.doc, self))
659 733
660 # Add empty References section 734 # Add empty References section
661 root.appendChild(self.doc.createElement('References')) 735 root.appendChild(self.doc.createElement('References'))
662 736
663 # Add files section 737 # Add files section
664 root.appendChild(self.files.CreateElement(self.doc, self.CreateFileElement)) 738 root.appendChild(self.files.CreateElement(self.doc, self.CreateFileElement))
665 739
666 # Add empty Globals section 740 # Add empty Globals section
667 root.appendChild(self.doc.createElement('Globals')) 741 root.appendChild(self.doc.createElement('Globals'))
668 742
669 def CreateFileElement(self, file): 743 def CreateFileElement(self, file):
670 """Create a DOM node for the specified file. 744 """Create a DOM node for the specified file.
671 745
672 Args: 746 Args:
673 file: The file Node being considered. 747 file: The file Node being considered.
674 748
675 Returns: 749 Returns:
676 A DOM Node for the File, with a relative path to the current 750 A DOM Node for the File, with a relative path to the current
677 project object, and any file configurations attached to the 751 project object, and any file configurations attached to the
678 project. 752 project.
679 """ 753 """
680 754
681 node = self.doc.createElement('File') 755 node = self.doc.createElement('File')
682 node.setAttribute('RelativePath', self.get_rel_path(file)) 756 node.setAttribute('RelativePath', self.get_rel_path(file))
683 for c in self.file_configurations.get(file, []): 757 for c in self.file_configurations.get(file, []):
684 node.appendChild(c.CreateElement(self.doc)) 758 node.appendChild(c.CreateElement(self.doc, self))
685 return node 759 return node
686 760
687 def _AddFileConfigurationDifferences(self, target, source, base_env, file_env) : 761 def VCCLCompilerTool(self, args):
762 default_attrs = {
763 'BufferSecurityCheck' : "false",
764 'CompileAs' : 0, # default
765 'DebugInformationFormat' : 0, # TODO(???)
766 'DisableSpecificWarnings' : [],
767 'EnableFiberSafeOptimizations' : "false",
768 'EnableFunctionLevelLinking' : "false",
769 'EnableIntrinsicFunctions' : "false",
770 'FavorSizeOrSpeed' : 0, # favorNone
771 'InlineFunctionExpansion' : 1, # expandDisable
772 'MinimalRebuild' : "false",
773 'OmitFramePointers' : "false",
774 'Optimization' : 1, # optimizeDisabled TODO(???)
775 'PreprocessorDefinitions' : [],
776 'RuntimeLibrary' : TODO,
777 'RuntimeTypeInfo' : "false",
778 'StringPooling' : "false",
779 'SuppressStartupBanner' : "false",
780 'WarningAsError' : "false",
781 'WarningLevel' : 1, # warningLevel_1
782 'WholeProgramOptimization' : "false",
783 }
784
785 tool = MSVSTool('VCCLCompilerTool', **default_attrs)
786 attrs = tool.attrs
787
788 for arg in args:
789 if arg in ('/c',):
790 continue
791 if arg.startswith('/Fo'):
792 continue
793 if arg.startswith('/D'):
794 attrs['PreprocessorDefinitions'].append(arg[2:])
795 elif arg == '/EH':
796 attrs['ExceptionHandling'] = 0
797 elif arg == '/GF':
798 attrs['StringPooling'] = "true"
799 elif arg == '/GL':
800 attrs['WholeProgramOptimization'] = "true"
801 elif arg == '/GM':
802 attrs['MinimalRebuild'] = "true"
803 elif arg == '/GR-':
804 attrs['RuntimeTypeInfo'] = "true"
805 elif arg == '/Gs':
806 attrs['BufferSecurityCheck'] = "true"
807 elif arg == '/Gs-':
808 attrs['BufferSecurityCheck'] = "false"
809 elif arg == '/GT':
810 attrs['EnableFiberSafeOptimizations'] = "true"
811 elif arg == '/Gy':
812 attrs['EnableFunctionLevelLinking'] = "true"
813 elif arg == '/MD':
814 attrs['RuntimeLibrary'] = 1 # rtMultiThreadedDebug
815 elif arg == '/MDd':
816 attrs['RuntimeLibrary'] = 2 # rtMultiThreadedDebugDLL
817 elif arg == '/MT':
818 attrs['RuntimeLibrary'] = 0 # rtMultiThreaded
819 elif arg == '/MTd':
820 attrs['RuntimeLibrary'] = 3 # rtMultiThreadedDLL
821 elif arg == '/nologo':
822 attrs['SuppressStartupBanner'] = "true"
823 elif arg == '/O1':
824 attrs['InlineFunctionExpansion'] = 4 # optimizeMinSpace
825 elif arg == '/O2':
826 attrs['InlineFunctionExpansion'] = 3 # optimizeMaxSpeed
827 elif arg == '/Ob1':
828 attrs['InlineFunctionExpansion'] = 2 # expandOnlyInline
829 elif arg == '/Ob2':
830 attrs['InlineFunctionExpansion'] = 0 # expandAnySuitable
831 elif arg == '/Od':
832 attrs['Optimization'] = 0
833 elif arg == '/Oi':
834 attrs['EnableIntrinsicFunctions'] = "true"
835 elif arg == '/Os':
836 attrs['FavorSizeOrSpeed'] = 1 # favorSize
837 elif arg == '/Ot':
838 attrs['FavorSizeOrSpeed'] = 2 # favorSpeed
839 elif arg == '/Ox':
840 attrs['Optimization'] = 2 # optimizeFull
841 elif arg == '/Oy':
842 attrs['OmitFramePointers'] = "true"
843 elif arg == '/Oy-':
844 attrs['TODO'] = "true"
845 elif arg in ('/Tc', '/TC'):
846 attrs['CompileAs'] = 1 # compileAsC
847 elif arg in ('/Tp', '/TP'):
848 attrs['CompileAs'] = 2 # compileAsCPlusPlus
849 elif arg == '/WX':
850 attrs['WarnAsError'] = "true"
851 elif arg.startswith('/W'):
852 attrs['WarningLevel'] = int(arg[2:]) # 0 through 4
853 elif arg.startswith('/wd'):
854 attrs['DisableSpecificWarnings'].append(str(arg[3:]))
855 elif arg == '/Z7':
856 attrs['DebugInformationFormat'] = 3 # debugOldSytleInfo TODO(???)
857 elif arg == '/Zd':
858 attrs['DebugInformationFormat'] = 0 # debugDisabled
859 elif arg == '/Zi':
860 attrs['DebugInformationFormat'] = 2 # debugEnabled TODO(???)
861 elif arg == '/ZI':
862 attrs['DebugInformationFormat'] = 1 # debugEditAndContinue TODO(???)
863
864 cppdefines = attrs['PreprocessorDefinitions']
865 if cppdefines:
866 attrs['PreprocessorDefinitions'] = ';'.join(cppdefines)
867 warnings = attrs['DisableSpecificWarnings']
868 if warnings:
869 warnings = SCons.Util.uniquer(warnings)
870 attrs['DisableSpecificWarnings'] = ';'.join(warnings)
871
872 return tool
873
874 def VCLibrarianTool(self, args):
875 default_attrs = {
876 'LinkTimeCodeGeneration' : "false",
877 'SuppressStartupBanner' : "false",
878 }
879
880 tool = MSVSTool('VCLibrarianTool', **default_attrs)
881 attrs = tool.attrs
882
883 for arg in args:
884 if arg.startswith('/OUT'):
885 continue
886 if arg == '/ltcg':
887 attrs['LinkTimeCodeGeneration'] = "true"
888 elif arg == '/nologo':
889 attrs['SuppressStartupBanner'] = "true"
890
891 return tool
892
893 def VCLinkerTool(self, args):
894 default_attrs = {
895 'LinkIncremental' : "false",
896 'LinkTimeCodeGeneration' : "false",
897 'EnableCOMDATFolding' : TODO,
898 'OptimizeForWindows98' : TODO,
899 'OptimizeReferences' : TODO,
900 'Profile' : "false",
901 'SuppressStartupBanner' : "false",
902 }
903
904 tool = MSVSTool('VCLinkerTool', **default_attrs)
905 attrs = tool.attrs
906
907 for arg in args:
908 if arg == '':
909 continue
910 if arg == '/INCREMENTAL':
911 attrs['LinkIncremental'] = "true"
912 elif arg == '/INCREMENTAL:NO':
913 attrs['LinkIncremental'] = "false"
914 elif arg == '/LTCG':
915 attrs['LinkTimeCodeGeneration'] = "true"
916 elif arg == '/nologo':
917 attrs['SuppressStartupBanner'] = "true"
918 elif arg == '/OPT:NOICF':
919 attrs['EnableCOMDATFolding'] = 2 #
920 elif arg == '/OPT:NOWIN98':
921 attrs['OptimizeForWindows98'] = 1 #
922 elif arg == '/OPT:REF':
923 attrs['OptimizeReferences'] = 2 #
924 elif arg == '/PROFILE':
925 attrs['Profile'] = "true"
926
927 return tool
928
929 command_to_tool_map = {
930 'cl' : 'VCCLCompilerTool',
931 'cl.exe' : 'VCCLCompilerTool',
932 'lib' : 'VCLibrarianTool',
933 'lib.exe' : 'VCLibrarianTool',
934 'link' : 'VCLinkerTool',
935 'link.exe' : 'VCLinkerTool',
936 }
937
938 def cl_to_tool(self, args):
939 command = os.path.basename(args[0])
940 method_name = self.command_to_tool_map.get(command)
941 if not method_name:
942 return None
943 return getattr(self, method_name)(args[1:])
944
945 def _AddFileConfigurationDifferences(self, target, source, base_env, file_env, name):
688 """Adds a per-file configuration. 946 """Adds a per-file configuration.
689 947
690 Args: 948 Args:
691 target: The target being built from the source. 949 target: The target being built from the source.
692 source: The source to which the file configuration is being added. 950 source: The source to which the file configuration is being added.
693 base_env: The base construction environment for the project. 951 base_env: The base construction environment for the project.
694 Differences from this will go into the FileConfiguration 952 Differences from this will go into the FileConfiguration
695 in the project file. 953 in the project file.
696 file_env: The construction environment for the target, containing 954 file_env: The construction environment for the target, containing
697 the per-target settings. 955 the per-target settings.
698 """ 956 """
699 pass 957 executor = target.get_executor()
958 base_cl = map(str, base_env.subst_list(executor)[0])
959 file_cl = map(str, file_env.subst_list(executor)[0])
960 if base_cl == file_cl:
961 return
962
963 base_tool = self.cl_to_tool(base_cl)
964 file_tool = self.cl_to_tool(file_cl)
965
966 file_tool.diff(base_tool)
967
968 self.AddFileConfig(source, name, tools=[file_tool])
700 969
701 def _AddFileConfigurations(self, env): 970 def _AddFileConfigurations(self, env):
702 """Adds per-file configurations for the buildtarget's sources. 971 """Adds per-file configurations for the buildtarget's sources.
703 972
704 Args: 973 Args:
705 env: The base construction environment for the project. 974 env: The base construction environment for the project.
706 """ 975 """
707 if not self.buildtargets: 976 if not self.buildtargets:
708 return 977 return
709 978
710 bt = self.buildtargets[0] 979 for bt in self.buildtargets:
711 additional_files = [] 980 executor = bt.get_executor()
712 for t in bt.sources: 981 build_env = bt.get_build_env()
982 bt_cl = map(str, build_env.subst_list(executor)[0])
983 tool = self.cl_to_tool(bt_cl)
984 default_tool = self.cl_to_tool([bt_cl[0]])
985 if default_tool:
986 tool.diff(default_tool)
987 else:
988 print "no tool for %r" % bt_cl[0]
989 for t in bt.sources:
713 e = t.get_build_env() 990 e = t.get_build_env()
991 additional_files = SCons.Util.UniqueList()
714 for s in t.sources: 992 for s in t.sources:
715 s = env.arg2nodes([s])[0] 993 s = env.arg2nodes([s])[0].srcnode()
716 if not self.FindFile(s): 994 if not self.FindFile(s):
717 additional_files.append(s) 995 additional_files.append(s)
718 if not env is e: 996 if not build_env is e:
719 self._AddFileConfigurationDifferences(t, s, env, e) 997 # TODO(sgk): This test may be bogus, but it works for now.
720 self.AddFiles(additional_files) 998 # We're trying to figure out if the file configuration
999 # differences need to be added one per build target, or one
1000 # per configuration for the entire project. The assumption
1001 # is that if the number of buildtargets configured matches
1002 # the number of project configurations, that we use those
1003 # in preference to the project configurations.
1004 if len(self.buildtargets) == len(self.configurations):
1005 self._AddFileConfigurationDifferences(t, s, build_env, e, e.subst( '$MSVSCONFIGURATIONNAME'))
1006 else:
1007 for config in self.configurations:
1008 self._AddFileConfigurationDifferences(t, s, build_env, e, config .Name)
1009 self._MergeFiles(self.files, additional_files)
721 1010
722 def Write(self, env): 1011 def Write(self, env):
723 """Writes the project file.""" 1012 """Writes the project file."""
1013 for flist in self.file_lists:
1014 self._FilesToSourceFiles(flist)
1015 self._MergeFiles(self.files, flist)
1016 for k, v in self.file_configurations.items():
1017 self.file_configurations[str(k)] = v
1018 k = self.env.File(k).srcnode()
1019 self.file_configurations[k] = v
1020 self.file_configurations[str(k)] = v
724 self._AddFileConfigurations(env) 1021 self._AddFileConfigurations(env)
725 1022
726 self.Create() 1023 self.Create()
727 1024
728 f = open(str(self.msvs_node), 'wt') 1025 f = open(str(self), 'wt')
729 f.write(self.formatMSVSProjectXML(self.doc)) 1026 f.write(self.formatMSVSProjectXML(self.doc))
730 f.close() 1027 f.close()
731 1028
732 # Methods for formatting XML as nearly identically to Microsoft's 1029 # Methods for formatting XML as nearly identically to Microsoft's
733 # .vcproj output as we can practically make it. 1030 # .vcproj output as we can practically make it.
734 # 1031 #
735 # The general design here is copied from: 1032 # The general design here is copied from:
736 # 1033 #
737 # Bruce Eckels' MindView, Inc: 12-09-04 XML Oddyssey 1034 # Bruce Eckels' MindView, Inc: 12-09-04 XML Oddyssey
738 # http://www.mindview.net/WebLog/log-0068 1035 # http://www.mindview.net/WebLog/log-0068
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
782 'ConfigurationType', 1079 'ConfigurationType',
783 'InheritedPropertySheets', 1080 'InheritedPropertySheets',
784 ], 1081 ],
785 'FileConfiguration' : [ 1082 'FileConfiguration' : [
786 'Name', 1083 'Name',
787 'ExcludedFromBuild', 1084 'ExcludedFromBuild',
788 ], 1085 ],
789 'Tool' : [ 1086 'Tool' : [
790 'Name', 1087 'Name',
791 'DisableSpecificWarnings', 1088 'DisableSpecificWarnings',
1089
1090 'PreprocessorDefinitions',
1091 'UsePrecompiledHeader',
1092 'PrecompiledHeaderThrough',
1093 'ForcedIncludeFiles',
792 ], 1094 ],
793 'VisualStudioProject' : [ 1095 'VisualStudioProject' : [
794 'ProjectType', 1096 'ProjectType',
795 'Version', 1097 'Version',
796 'Name', 1098 'Name',
797 'ProjectGUID', 1099 'ProjectGUID',
798 'RootNamespace', 1100 'RootNamespace',
799 'Keyword', 1101 'Keyword',
800 ], 1102 ],
801 } 1103 }
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after
1055 if not SCons.Util.is_String(item): 1357 if not SCons.Util.is_String(item):
1056 return item 1358 return item
1057 item = env.subst(item) 1359 item = env.subst(item)
1058 result = env.fs._lookup(item, None, _MSVSSolution, create=1) 1360 result = env.fs._lookup(item, None, _MSVSSolution, create=1)
1059 result.initialize(env, item, *args, **kw) 1361 result.initialize(env, item, *args, **kw)
1060 LookupAdd(item, result) 1362 LookupAdd(item, result)
1061 return result 1363 return result
1062 1364
1063 import __builtin__ 1365 import __builtin__
1064 1366
1367 __builtin__.MSVSConfig = MSVSConfig
1065 __builtin__.MSVSFilter = MSVSFilter 1368 __builtin__.MSVSFilter = MSVSFilter
1066 __builtin__.MSVSProject = MSVSProject 1369 __builtin__.MSVSProject = MSVSProject
1067 __builtin__.MSVSSolution = MSVSSolution 1370 __builtin__.MSVSSolution = MSVSSolution
1068 __builtin__.MSVSTool = MSVSTool 1371 __builtin__.MSVSTool = MSVSTool
OLDNEW
« no previous file with comments | « net/tools/tld_cleanup/tld_cleanup.scons ('k') | site_scons/site_tools/chromium_builders.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698