1c1ced77af959d11dd80252ab471e89906ea70f09maruel@chromium.org#!/usr/bin/env python 2ea13fb0eee7f81ce6037b95339566fa0fb9d7bd9thomasvl@chromium.org 346d34d835a9fb416adc83e8cf4aba29204bece0bbradnelson@google.com# Copyright (c) 2012 Google Inc. All rights reserved. 4ea13fb0eee7f81ce6037b95339566fa0fb9d7bd9thomasvl@chromium.org# Use of this source code is governed by a BSD-style license that can be 5ea13fb0eee7f81ce6037b95339566fa0fb9d7bd9thomasvl@chromium.org# found in the LICENSE file. 64787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org 74787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org"""Make the format of a vcproj really pretty. 84787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org 94787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org This script normalize and sort an xml. It also fetches all the properties 104787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org inside linked vsprops and include them explicitly in the vcproj. 11ea13fb0eee7f81ce6037b95339566fa0fb9d7bd9thomasvl@chromium.org 124787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org It outputs the resulting xml to stdout. 134787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org""" 144787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org 154787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org__author__ = 'nsylvain (Nicolas Sylvain)' 164787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org 174787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.orgimport os 184787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.orgimport sys 194787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org 204787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.orgfrom xml.dom.minidom import parse 214787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.orgfrom xml.dom.minidom import Node 224787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org 234787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.orgREPLACEMENTS = dict() 24ff3b11917354598c00dd7bef08e851e3add8985cnsylvain@chromium.orgARGUMENTS = None 254787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org 26c1ced77af959d11dd80252ab471e89906ea70f09maruel@chromium.org 27c1ced77af959d11dd80252ab471e89906ea70f09maruel@chromium.orgclass CmpTuple(object): 284787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org """Compare function between 2 tuple.""" 294787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org def __call__(self, x, y): 3046d34d835a9fb416adc83e8cf4aba29204bece0bbradnelson@google.com return cmp(x[0], y[0]) 314787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org 32c1ced77af959d11dd80252ab471e89906ea70f09maruel@chromium.org 33c1ced77af959d11dd80252ab471e89906ea70f09maruel@chromium.orgclass CmpNode(object): 344787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org """Compare function between 2 xml nodes.""" 354787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org 3646d34d835a9fb416adc83e8cf4aba29204bece0bbradnelson@google.com def __call__(self, x, y): 3746d34d835a9fb416adc83e8cf4aba29204bece0bbradnelson@google.com def get_string(node): 3846d34d835a9fb416adc83e8cf4aba29204bece0bbradnelson@google.com node_string = "node" 3946d34d835a9fb416adc83e8cf4aba29204bece0bbradnelson@google.com node_string += node.nodeName 4046d34d835a9fb416adc83e8cf4aba29204bece0bbradnelson@google.com if node.nodeValue: 4146d34d835a9fb416adc83e8cf4aba29204bece0bbradnelson@google.com node_string += node.nodeValue 424787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org 4346d34d835a9fb416adc83e8cf4aba29204bece0bbradnelson@google.com if node.attributes: 4446d34d835a9fb416adc83e8cf4aba29204bece0bbradnelson@google.com # We first sort by name, if present. 4546d34d835a9fb416adc83e8cf4aba29204bece0bbradnelson@google.com node_string += node.getAttribute("Name") 464787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org 4746d34d835a9fb416adc83e8cf4aba29204bece0bbradnelson@google.com all_nodes = [] 4846d34d835a9fb416adc83e8cf4aba29204bece0bbradnelson@google.com for (name, value) in node.attributes.items(): 4946d34d835a9fb416adc83e8cf4aba29204bece0bbradnelson@google.com all_nodes.append((name, value)) 504787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org 5146d34d835a9fb416adc83e8cf4aba29204bece0bbradnelson@google.com all_nodes.sort(CmpTuple()) 5246d34d835a9fb416adc83e8cf4aba29204bece0bbradnelson@google.com for (name, value) in all_nodes: 5346d34d835a9fb416adc83e8cf4aba29204bece0bbradnelson@google.com node_string += name 5446d34d835a9fb416adc83e8cf4aba29204bece0bbradnelson@google.com node_string += value 554787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org 5646d34d835a9fb416adc83e8cf4aba29204bece0bbradnelson@google.com return node_string 574787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org 5846d34d835a9fb416adc83e8cf4aba29204bece0bbradnelson@google.com return cmp(get_string(x), get_string(y)) 594787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org 60c1ced77af959d11dd80252ab471e89906ea70f09maruel@chromium.org 614787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.orgdef PrettyPrintNode(node, indent=0): 624787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org if node.nodeType == Node.TEXT_NODE: 634787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org if node.data.strip(): 644787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org print '%s%s' % (' '*indent, node.data.strip()) 654787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org return 664787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org 674787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org if node.childNodes: 684787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org node.normalize() 694787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org # Get the number of attributes 704787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org attr_count = 0 714787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org if node.attributes: 724787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org attr_count = node.attributes.length 734787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org 744787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org # Print the main tag 754787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org if attr_count == 0: 764787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org print '%s<%s>' % (' '*indent, node.nodeName) 774787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org else: 784787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org print '%s<%s' % (' '*indent, node.nodeName) 794787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org 804787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org all_attributes = [] 814787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org for (name, value) in node.attributes.items(): 824787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org all_attributes.append((name, value)) 834787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org all_attributes.sort(CmpTuple()) 844787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org for (name, value) in all_attributes: 854787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org print '%s %s="%s"' % (' '*indent, name, value) 864787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org print '%s>' % (' '*indent) 874787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org if node.nodeValue: 884787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org print '%s %s' % (' '*indent, node.nodeValue) 894787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org 904787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org for sub_node in node.childNodes: 914787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org PrettyPrintNode(sub_node, indent=indent+2) 924787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org print '%s</%s>' % (' '*indent, node.nodeName) 937531c1c00b3bdb40dcb9407052fa03d01b9d605fnsylvain@chromium.org 94c1ced77af959d11dd80252ab471e89906ea70f09maruel@chromium.org 957531c1c00b3bdb40dcb9407052fa03d01b9d605fnsylvain@chromium.orgdef FlattenFilter(node): 967531c1c00b3bdb40dcb9407052fa03d01b9d605fnsylvain@chromium.org """Returns a list of all the node and sub nodes.""" 977531c1c00b3bdb40dcb9407052fa03d01b9d605fnsylvain@chromium.org node_list = [] 987531c1c00b3bdb40dcb9407052fa03d01b9d605fnsylvain@chromium.org 997531c1c00b3bdb40dcb9407052fa03d01b9d605fnsylvain@chromium.org if (node.attributes and 1007531c1c00b3bdb40dcb9407052fa03d01b9d605fnsylvain@chromium.org node.getAttribute('Name') == '_excluded_files'): 1017531c1c00b3bdb40dcb9407052fa03d01b9d605fnsylvain@chromium.org # We don't add the "_excluded_files" filter. 1027531c1c00b3bdb40dcb9407052fa03d01b9d605fnsylvain@chromium.org return [] 1037531c1c00b3bdb40dcb9407052fa03d01b9d605fnsylvain@chromium.org 1047531c1c00b3bdb40dcb9407052fa03d01b9d605fnsylvain@chromium.org for current in node.childNodes: 1057531c1c00b3bdb40dcb9407052fa03d01b9d605fnsylvain@chromium.org if current.nodeName == 'Filter': 1067531c1c00b3bdb40dcb9407052fa03d01b9d605fnsylvain@chromium.org node_list.extend(FlattenFilter(current)) 1077531c1c00b3bdb40dcb9407052fa03d01b9d605fnsylvain@chromium.org else: 1087531c1c00b3bdb40dcb9407052fa03d01b9d605fnsylvain@chromium.org node_list.append(current) 1097531c1c00b3bdb40dcb9407052fa03d01b9d605fnsylvain@chromium.org 1107531c1c00b3bdb40dcb9407052fa03d01b9d605fnsylvain@chromium.org return node_list 1117531c1c00b3bdb40dcb9407052fa03d01b9d605fnsylvain@chromium.org 112c1ced77af959d11dd80252ab471e89906ea70f09maruel@chromium.org 113ff3b11917354598c00dd7bef08e851e3add8985cnsylvain@chromium.orgdef FixFilenames(filenames, current_directory): 114ff3b11917354598c00dd7bef08e851e3add8985cnsylvain@chromium.org new_list = [] 115ff3b11917354598c00dd7bef08e851e3add8985cnsylvain@chromium.org for filename in filenames: 116ff3b11917354598c00dd7bef08e851e3add8985cnsylvain@chromium.org if filename: 117ff3b11917354598c00dd7bef08e851e3add8985cnsylvain@chromium.org for key in REPLACEMENTS: 118ff3b11917354598c00dd7bef08e851e3add8985cnsylvain@chromium.org filename = filename.replace(key, REPLACEMENTS[key]) 119ff3b11917354598c00dd7bef08e851e3add8985cnsylvain@chromium.org os.chdir(current_directory) 120ff3b11917354598c00dd7bef08e851e3add8985cnsylvain@chromium.org filename = filename.strip('"\' ') 121ff3b11917354598c00dd7bef08e851e3add8985cnsylvain@chromium.org if filename.startswith('$'): 122ff3b11917354598c00dd7bef08e851e3add8985cnsylvain@chromium.org new_list.append(filename) 123ff3b11917354598c00dd7bef08e851e3add8985cnsylvain@chromium.org else: 124ff3b11917354598c00dd7bef08e851e3add8985cnsylvain@chromium.org new_list.append(os.path.abspath(filename)) 125ff3b11917354598c00dd7bef08e851e3add8985cnsylvain@chromium.org return new_list 126ff3b11917354598c00dd7bef08e851e3add8985cnsylvain@chromium.org 127c1ced77af959d11dd80252ab471e89906ea70f09maruel@chromium.org 128ff3b11917354598c00dd7bef08e851e3add8985cnsylvain@chromium.orgdef AbsoluteNode(node): 129c1ced77af959d11dd80252ab471e89906ea70f09maruel@chromium.org """Makes all the properties we know about in this node absolute.""" 130ff3b11917354598c00dd7bef08e851e3add8985cnsylvain@chromium.org if node.attributes: 131ff3b11917354598c00dd7bef08e851e3add8985cnsylvain@chromium.org for (name, value) in node.attributes.items(): 132ff3b11917354598c00dd7bef08e851e3add8985cnsylvain@chromium.org if name in ['InheritedPropertySheets', 'RelativePath', 133ff3b11917354598c00dd7bef08e851e3add8985cnsylvain@chromium.org 'AdditionalIncludeDirectories', 134ff3b11917354598c00dd7bef08e851e3add8985cnsylvain@chromium.org 'IntermediateDirectory', 'OutputDirectory', 135ff3b11917354598c00dd7bef08e851e3add8985cnsylvain@chromium.org 'AdditionalLibraryDirectories']: 136ff3b11917354598c00dd7bef08e851e3add8985cnsylvain@chromium.org # We want to fix up these paths 137ff3b11917354598c00dd7bef08e851e3add8985cnsylvain@chromium.org path_list = value.split(';') 138ff3b11917354598c00dd7bef08e851e3add8985cnsylvain@chromium.org new_list = FixFilenames(path_list, os.path.dirname(ARGUMENTS[1])) 139ff3b11917354598c00dd7bef08e851e3add8985cnsylvain@chromium.org node.setAttribute(name, ';'.join(new_list)) 140ff3b11917354598c00dd7bef08e851e3add8985cnsylvain@chromium.org if not value: 141ff3b11917354598c00dd7bef08e851e3add8985cnsylvain@chromium.org node.removeAttribute(name) 142ff3b11917354598c00dd7bef08e851e3add8985cnsylvain@chromium.org 143c1ced77af959d11dd80252ab471e89906ea70f09maruel@chromium.org 1444787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.orgdef CleanupVcproj(node): 145c1ced77af959d11dd80252ab471e89906ea70f09maruel@chromium.org """For each sub node, we call recursively this function.""" 1464787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org for sub_node in node.childNodes: 147ff3b11917354598c00dd7bef08e851e3add8985cnsylvain@chromium.org AbsoluteNode(sub_node) 1484787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org CleanupVcproj(sub_node) 1494787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org 1504787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org # Normalize the node, and remove all extranous whitespaces. 1514787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org for sub_node in node.childNodes: 1524787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org if sub_node.nodeType == Node.TEXT_NODE: 15346d34d835a9fb416adc83e8cf4aba29204bece0bbradnelson@google.com sub_node.data = sub_node.data.replace("\r", "") 15446d34d835a9fb416adc83e8cf4aba29204bece0bbradnelson@google.com sub_node.data = sub_node.data.replace("\n", "") 15546d34d835a9fb416adc83e8cf4aba29204bece0bbradnelson@google.com sub_node.data = sub_node.data.rstrip() 156ea13fb0eee7f81ce6037b95339566fa0fb9d7bd9thomasvl@chromium.org 1577531c1c00b3bdb40dcb9407052fa03d01b9d605fnsylvain@chromium.org # Fix all the semicolon separated attributes to be sorted, and we also 1587531c1c00b3bdb40dcb9407052fa03d01b9d605fnsylvain@chromium.org # remove the dups. 1594787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org if node.attributes: 1604787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org for (name, value) in node.attributes.items(): 1617531c1c00b3bdb40dcb9407052fa03d01b9d605fnsylvain@chromium.org sorted_list = sorted(value.split(';')) 162ea13fb0eee7f81ce6037b95339566fa0fb9d7bd9thomasvl@chromium.org unique_list = [] 16346d34d835a9fb416adc83e8cf4aba29204bece0bbradnelson@google.com for i in sorted_list: 16446d34d835a9fb416adc83e8cf4aba29204bece0bbradnelson@google.com if not unique_list.count(i): 16546d34d835a9fb416adc83e8cf4aba29204bece0bbradnelson@google.com unique_list.append(i) 1667531c1c00b3bdb40dcb9407052fa03d01b9d605fnsylvain@chromium.org node.setAttribute(name, ';'.join(unique_list)) 1674787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org if not value: 1684787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org node.removeAttribute(name) 1694787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org 1704787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org if node.childNodes: 1714787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org node.normalize() 172ea13fb0eee7f81ce6037b95339566fa0fb9d7bd9thomasvl@chromium.org 1734787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org # For each node, take a copy, and remove it from the list. 1744787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org node_array = [] 1754787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org while node.childNodes and node.childNodes[0]: 1767531c1c00b3bdb40dcb9407052fa03d01b9d605fnsylvain@chromium.org # Take a copy of the node and remove it from the list. 1777531c1c00b3bdb40dcb9407052fa03d01b9d605fnsylvain@chromium.org current = node.childNodes[0] 1787531c1c00b3bdb40dcb9407052fa03d01b9d605fnsylvain@chromium.org node.removeChild(current) 1797531c1c00b3bdb40dcb9407052fa03d01b9d605fnsylvain@chromium.org 1807531c1c00b3bdb40dcb9407052fa03d01b9d605fnsylvain@chromium.org # If the child is a filter, we want to append all its children 1817531c1c00b3bdb40dcb9407052fa03d01b9d605fnsylvain@chromium.org # to this same list. 1827531c1c00b3bdb40dcb9407052fa03d01b9d605fnsylvain@chromium.org if current.nodeName == 'Filter': 1837531c1c00b3bdb40dcb9407052fa03d01b9d605fnsylvain@chromium.org node_array.extend(FlattenFilter(current)) 1847531c1c00b3bdb40dcb9407052fa03d01b9d605fnsylvain@chromium.org else: 1857531c1c00b3bdb40dcb9407052fa03d01b9d605fnsylvain@chromium.org node_array.append(current) 1867531c1c00b3bdb40dcb9407052fa03d01b9d605fnsylvain@chromium.org 187ea13fb0eee7f81ce6037b95339566fa0fb9d7bd9thomasvl@chromium.org 1884787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org # Sort the list. 1894787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org node_array.sort(CmpNode()) 1904787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org 1914787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org # Insert the nodes in the correct order. 1924787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org for new_node in node_array: 1934787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org # But don't append empty tool node. 1944787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org if new_node.nodeName == 'Tool': 1954787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org if new_node.attributes and new_node.attributes.length == 1: 1964787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org # This one was empty. 1974787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org continue 198ff3b11917354598c00dd7bef08e851e3add8985cnsylvain@chromium.org if new_node.nodeName == 'UserMacro': 199ff3b11917354598c00dd7bef08e851e3add8985cnsylvain@chromium.org continue 2004787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org node.appendChild(new_node) 2014787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org 202c1ced77af959d11dd80252ab471e89906ea70f09maruel@chromium.org 2034787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.orgdef GetConfiguationNodes(vcproj): 2044787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org #TODO(nsylvain): Find a better way to navigate the xml. 2054787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org nodes = [] 2064787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org for node in vcproj.childNodes: 2074787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org if node.nodeName == "Configurations": 2084787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org for sub_node in node.childNodes: 2094787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org if sub_node.nodeName == "Configuration": 2104787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org nodes.append(sub_node) 2114787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org 2124787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org return nodes 2134787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org 214c1ced77af959d11dd80252ab471e89906ea70f09maruel@chromium.org 2154787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.orgdef GetChildrenVsprops(filename): 2164787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org dom = parse(filename) 2174787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org if dom.documentElement.attributes: 2184787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org vsprops = dom.documentElement.getAttribute('InheritedPropertySheets') 2194787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org return FixFilenames(vsprops.split(';'), os.path.dirname(filename)) 2204787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org return [] 2214787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org 2224787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.orgdef SeekToNode(node1, child2): 2234787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org # A text node does not have properties. 2244787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org if child2.nodeType == Node.TEXT_NODE: 2254787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org return None 2264787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org 2274787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org # Get the name of the current node. 2284787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org current_name = child2.getAttribute("Name") 2294787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org if not current_name: 2304787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org # There is no name. We don't know how to merge. 2314787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org return None 2324787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org 2334787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org # Look through all the nodes to find a match. 2344787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org for sub_node in node1.childNodes: 2354787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org if sub_node.nodeName == child2.nodeName: 2364787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org name = sub_node.getAttribute("Name") 2374787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org if name == current_name: 2384787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org return sub_node 2394787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org 2404787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org # No match. We give up. 2414787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org return None 2424787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org 243c1ced77af959d11dd80252ab471e89906ea70f09maruel@chromium.org 2444787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.orgdef MergeAttributes(node1, node2): 2454787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org # No attributes to merge? 2464787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org if not node2.attributes: 2474787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org return 2484787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org 2494787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org for (name, value2) in node2.attributes.items(): 2504787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org # Don't merge the 'Name' attribute. 2514787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org if name == 'Name': 2524787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org continue 2534787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org value1 = node1.getAttribute(name) 2544787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org if value1: 2554787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org # The attribute exist in the main node. If it's equal, we leave it 2564787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org # untouched, otherwise we concatenate it. 2574787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org if value1 != value2: 2584787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org node1.setAttribute(name, ';'.join([value1, value2])) 2594787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org else: 2604787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org # The attribute does nto exist in the main node. We append this one. 2614787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org node1.setAttribute(name, value2) 2624787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org 2634787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org # If the attribute was a property sheet attributes, we remove it, since 2644787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org # they are useless. 2654787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org if name == 'InheritedPropertySheets': 2664787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org node1.removeAttribute(name) 2674787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org 268c1ced77af959d11dd80252ab471e89906ea70f09maruel@chromium.org 2694787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.orgdef MergeProperties(node1, node2): 2704787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org MergeAttributes(node1, node2) 2714787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org for child2 in node2.childNodes: 2724787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org child1 = SeekToNode(node1, child2) 2734787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org if child1: 2744787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org MergeProperties(child1, child2) 2754787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org else: 2764787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org node1.appendChild(child2.cloneNode(True)) 2774787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org 278c1ced77af959d11dd80252ab471e89906ea70f09maruel@chromium.org 279ff3b11917354598c00dd7bef08e851e3add8985cnsylvain@chromium.orgdef main(argv): 28046d34d835a9fb416adc83e8cf4aba29204bece0bbradnelson@google.com """Main function of this vcproj prettifier.""" 281ff3b11917354598c00dd7bef08e851e3add8985cnsylvain@chromium.org global ARGUMENTS 282ff3b11917354598c00dd7bef08e851e3add8985cnsylvain@chromium.org ARGUMENTS = argv 2834787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org 2844787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org # check if we have exactly 1 parameter. 285ff3b11917354598c00dd7bef08e851e3add8985cnsylvain@chromium.org if len(argv) < 2: 2864787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org print ('Usage: %s "c:\\path\\to\\vcproj.vcproj" [key1=value1] ' 287ff3b11917354598c00dd7bef08e851e3add8985cnsylvain@chromium.org '[key2=value2]' % argv[0]) 288c1ced77af959d11dd80252ab471e89906ea70f09maruel@chromium.org return 1 2894787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org 2904787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org # Parse the keys 291ff3b11917354598c00dd7bef08e851e3add8985cnsylvain@chromium.org for i in range(2, len(argv)): 292ff3b11917354598c00dd7bef08e851e3add8985cnsylvain@chromium.org (key, value) = argv[i].split('=') 2934787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org REPLACEMENTS[key] = value 2944787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org 2954787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org # Open the vcproj and parse the xml. 296ff3b11917354598c00dd7bef08e851e3add8985cnsylvain@chromium.org dom = parse(argv[1]) 2974787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org 2984787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org # First thing we need to do is find the Configuration Node and merge them 2994787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org # with the vsprops they include. 3004787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org for configuration_node in GetConfiguationNodes(dom.documentElement): 3014787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org # Get the property sheets associated with this configuration. 3024787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org vsprops = configuration_node.getAttribute('InheritedPropertySheets') 3034787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org 3044787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org # Fix the filenames to be absolute. 3054787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org vsprops_list = FixFilenames(vsprops.strip().split(';'), 306ff3b11917354598c00dd7bef08e851e3add8985cnsylvain@chromium.org os.path.dirname(argv[1])) 3074787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org 3084787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org # Extend the list of vsprops with all vsprops contained in the current 3094787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org # vsprops. 3104787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org for current_vsprops in vsprops_list: 31146d34d835a9fb416adc83e8cf4aba29204bece0bbradnelson@google.com vsprops_list.extend(GetChildrenVsprops(current_vsprops)) 3124787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org 3134787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org # Now that we have all the vsprops, we need to merge them. 3144787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org for current_vsprops in vsprops_list: 3154787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org MergeProperties(configuration_node, 3164787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org parse(current_vsprops).documentElement) 3174787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org 3184787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org # Now that everything is merged, we need to cleanup the xml. 3194787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org CleanupVcproj(dom.documentElement) 3204787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org 3214787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org # Finally, we use the prett xml function to print the vcproj back to the 3224787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org # user. 3234787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org #print dom.toprettyxml(newl="\n") 3244787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.org PrettyPrintNode(dom.documentElement) 325c1ced77af959d11dd80252ab471e89906ea70f09maruel@chromium.org return 0 326c1ced77af959d11dd80252ab471e89906ea70f09maruel@chromium.org 327ea13fb0eee7f81ce6037b95339566fa0fb9d7bd9thomasvl@chromium.org 3284787a79516a69bdfa3e5255d116a03d513d2b61ansylvain@chromium.orgif __name__ == '__main__': 329c1ced77af959d11dd80252ab471e89906ea70f09maruel@chromium.org sys.exit(main(sys.argv)) 330