使用python脚本批量修改vc工程文件
Posted clever101
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用python脚本批量修改vc工程文件相关的知识,希望对你有一定的参考价值。
作者:朱金灿
来源:clever101的专栏
问题描述
vc工程文件中的很多属性设置,比如输出目录、中间目录和输出文件名等等。使用vs单独操作设置较为繁琐,如果几十甚至上百个工程操作就更为繁琐了。于是决定编写一个python脚本来实现批量修改vc工程文件。
实现思路
首先我们打开一个vc工程文件,可以发现它本质上的一个xml文件。如下:
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>E23129FC-0417-462C-890C-D0EC20E735AB</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>WatermarkAssist</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<OutDir>D:\\Program Files (x86)\\Adobe\\Acrobat 11.0\\Acrobat\\plug_ins</OutDir>
<IntDir>..\\..\\..\\Intdir\\$(Configuration)_$(Platform)\\$(ProjectName)</IntDir>
<TargetExt>.api</TargetExt>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;WIN_PLATFORM;WIN32;_WINDOWS;WIN_ENV;ACRO_SDK_LEVEL=0x00060000;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\\..\\Headers\\SDK;..\\..\\Headers\\API;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalOptions>/EXPORT:PlugInMain</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;_WINDOWS;_USRDLL;WATERMARKASSIST_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;WATERMARKASSIST_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>NDEBUG;_WINDOWS;_USRDLL;WATERMARKASSIST_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="PIMain.c" />
<ClCompile Include="WatermarkAssist.cpp" />
<ClCompile Include="WatermarkAssistInit.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
因此我们使用python的xml解析库就可以解决问题了。我们看到这个xml文件也是比较容易读懂的,比如Condition="’$(Configuration)|$(Platform)’==‘Debug|Win32’">节点下的<OutDir>节点就是设置输出目录的,<IntDir>节点就是设置临时目录的。
关键代码
代码不复杂,关键有两处。一是使用python的xml解释库xml.etree.ElementTree解析vc工程文件之前需要先注册命名空间,代码如下:
ET.register_namespace('', "http://schemas.microsoft.com/developer/msbuild/2003")
二是脚本中的find_nodes函数的使用,调用代码如下:
import xml.etree.ElementTree as ET
from xml.etree.ElementTree import ElementTree,Element
#修改vc工程的输出目录和中间目录、设置输出文件名、pdb文件和导入库文件
def ModifyPrjProperty(tree):
#find_nodes函数负责找到PropertyGroup节点下的所有子节点
nodes = find_nodes(tree, 'http://schemas.microsoft.com/developer/msbuild/2003PropertyGroup')
for groupNode in nodes:
propertyNodes = groupNode.getchildren()
#遍历子节点
for propertyNode in propertyNodes:
if propertyNode.tag == 'http://schemas.microsoft.com/developer/msbuild/2003OutDir':
print 'finded OutDir'
#propertyNode.text = "..\\..\\\\..\\\\..\\\\OutDir\\\\$(Configuration)_$(Platform)"
propertyNode.text = "D:\\\\Program Files (x86)\\\\Adobe\\Acrobat 11.0\\\\Acrobat\\\\plug_ins"
continue
if propertyNode.tag == 'http://schemas.microsoft.com/developer/msbuild/2003IntDir':
print 'finded IntDir'
propertyNode.text = "..\\..\\..\\..\\Intdir\\$(Configuration)_$(Platform)\\$(ProjectName)"
continue
nodes = find_nodes(tree, 'http://schemas.microsoft.com/developer/msbuild/2003ItemDefinitionGroup')
for groupNode in nodes:
propertyNodes = groupNode.getchildren()
for propertyNode in propertyNodes:
if propertyNode.tag == 'http://schemas.microsoft.com/developer/msbuild/2003ClCompile':
ClCompileNodes = propertyNode
for ciNode in ClCompileNodes:
if ciNode.tag == 'http://schemas.microsoft.com/developer/msbuild/2003AssemblerListingLocation':
print 'finded AssemblerListingLocation'
ciNode.text = "$(IntDir)"
continue
if ciNode.tag == 'http://schemas.microsoft.com/developer/msbuild/2003ObjectFileName':
print 'finded ObjectFileName'
ciNode.text = "$(IntDir)"
continue
if ciNode.tag == 'http://schemas.microsoft.com/developer/msbuild/2003ProgramDataBaseFileName':
print 'finded ProgramDataBaseFileName'
ciNode.text = "$(IntDir)vc$(PlatformToolsetVersion).pdb"
continue
if ciNode.tag == 'http://schemas.microsoft.com/developer/msbuild/2003RuntimeLibrary':
print 'finded RuntimeLibrary'
ciNode.text = "MultiThreadedDebugDLL"
continue
if propertyNode.tag == 'http://schemas.microsoft.com/developer/msbuild/2003Link':
LinkNodes = propertyNode
for linkNode in LinkNodes:
if linkNode.tag == python脚本-批量修改文件名中相同的字符串