Skip to content

Instantly share code, notes, and snippets.

@jia-kai
Created September 5, 2016 13:26
Show Gist options
  • Save jia-kai/b59abfa3dd097ec80d90e9078997539d to your computer and use it in GitHub Desktop.
Save jia-kai/b59abfa3dd097ec80d90e9078997539d to your computer and use it in GitHub Desktop.
Modify vcxproj files programmatically
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import bs4
import argparse
import re
import os
class VcxprojModifier:
_args = None
_matchers = None
_pipelines = None
def __init__(self, args):
self._args = args
self._matchers = []
self._pipelines = []
if args.cond:
self._matchers.append(self._matcher_cond(args.cond))
for i in args.defines:
self._pipelines.append(self._pipeline_define(i))
def _pipeline_define(self, fpath):
defs = []
def add_defs(fpath):
with open(fpath) as fin:
for i in fin:
i = i.strip()
if i.startswith('#'):
assert i.startswith('#include')
add_defs(os.path.join(
os.path.dirname(fpath),
i.split(' ', 1)[1]))
else:
defs.append(i)
add_defs(fpath)
defs = ';'.join(defs)
print('defs:', defs)
def modify(item):
for t in item.select('PreprocessorDefinitions'):
t.string = defs
return modify
def _matcher_cond(self, cond):
def match(item, _rem=re.compile(cond)):
return _rem.search(item['Condition']) is not None
return match
def process(self, soup):
for i in soup.select('ItemDefinitionGroup'):
if all(m(i) for m in self._matchers):
print('matched:', i.name, i.attrs)
for j in self._pipelines:
j(i)
def main():
parser = argparse.ArgumentParser(
description='modify ItemDefinitionGroup in .vcxproj files',
formatter_class=argparse.ArgumentDefaultsHelpFormatter
)
parser.add_argument('-c', '--cond', help='regex for Condition to match '
'against ItemDefinitionGroup tags')
parser.add_argument('-d', '--defines', default=[], action='append',
help='a file to replace the content of '
'PreprocessorDefinitions; the file should contain one '
'definition per line')
parser.add_argument('inputs', nargs='+', help=
'input .vcxproj files; would be modified in-place')
args = parser.parse_args()
modifier = VcxprojModifier(args)
for i in args.inputs:
print('---------- processing', i)
with open(i) as fin:
header = fin.readline()
soup = bs4.BeautifulSoup(fin, 'xml')
modifier.process(soup)
with open(i, 'w') as fout:
if header[0] == '\ufeff':
fout.write(header[0])
fout.write(str(soup))
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment