使用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/2003}PropertyGroup')
    for groupNode in nodes:
        propertyNodes = groupNode.getchildren()
        #遍历子节点
        for propertyNode in propertyNodes:
            if propertyNode.tag == '{http://schemas.microsoft.com/developer/msbuild/2003}OutDir':
                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/2003}IntDir':
                print 'finded IntDir'
                propertyNode.text = "..\..\..\..\Intdir\$(Configuration)_$(Platform)\$(ProjectName)"
                continue
    nodes = find_nodes(tree, '{http://schemas.microsoft.com/developer/msbuild/2003}ItemDefinitionGroup')
    for groupNode in nodes:
        propertyNodes = groupNode.getchildren()
        for propertyNode in propertyNodes:
            if propertyNode.tag == '{http://schemas.microsoft.com/developer/msbuild/2003}ClCompile':
                ClCompileNodes = propertyNode
                for ciNode in ClCompileNodes:
                    if ciNode.tag == '{http://schemas.microsoft.com/developer/msbuild/2003}AssemblerListingLocation':
                        print 'finded AssemblerListingLocation'
                        ciNode.text = "$(IntDir)"
                        continue
                    if ciNode.tag == '{http://schemas.microsoft.com/developer/msbuild/2003}ObjectFileName':
                        print 'finded ObjectFileName'
                        ciNode.text = "$(IntDir)"
                        continue
                    if ciNode.tag == '{http://schemas.microsoft.com/developer/msbuild/2003}ProgramDataBaseFileName':
                        print 'finded ProgramDataBaseFileName'
                        ciNode.text = "$(IntDir)vc$(PlatformToolsetVersion).pdb"
                        continue
                    if ciNode.tag == '{http://schemas.microsoft.com/developer/msbuild/2003}RuntimeLibrary':
                        print 'finded RuntimeLibrary'
                        ciNode.text = "MultiThreadedDebugDLL"
                        continue
            if propertyNode.tag == '{http://schemas.microsoft.com/developer/msbuild/2003}Link':
                LinkNodes = propertyNode
                for linkNode in LinkNodes:
                    if linkNode.tag == '{http://schemas.microsoft.com/developer/msbuild/2003}OutputFile':
                        print 'finded OutputFile'
                        linkNode.text = "$(OutDir)\\$(ProjectName).api"
                        continue
                    if linkNode.tag == '{http://schemas.microsoft.com/developer/msbuild/2003}ProgramDatabaseFile':
                        print 'finded ProgramDatabaseFile'
                        linkNode.text = "$(OutDir)\\$(ProjectName).pdb"
                        continue
                    if linkNode.tag == '{http://schemas.microsoft.com/developer/msbuild/2003}ImportLibrary':
                        print 'finded ImportLibrary'
                        linkNode.text = "$(IntDir)\\$(ProjectName).lib"
                        continue
if __name__ == "__main__":
	ET.register_namespace('',
        "http://schemas.microsoft.com/developer/msbuild/2003")
    tree = ElementTree()
    priFileFile = 'D:\\MyProject\\test.vcxproj'
    tree.parse(priFileFile)
    #ModifyPrjOutputAndIntDir(tree)
    ModifyPrjProperty(tree)

完整的脚本代码已上传到CSDN下载频道,下载地址:用于批量修改VC工程文件的python脚本

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

clever101

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值