如何从外部列表设置链接器的输出文件(在 .vcxproj 中)
How to set linker's OutputFile (in .vcxproj) from external list
我有一堆用于 VS2017 的 C++ 项目 (.vcxproj),它们生成动态库 (DLL),它们的处理方式类似于 "plugins"(即它们由应用程序动态加载)。
偶尔我想根据文本文件中的某些列表更改生成的 DLL 名称(格式可能会更改):
ProjName1;DLL1
ProjName2;DLL2
...
第一列指定项目名称 ($(ProjectName)
),第二列指定所需的 DLL 名称 ($(TargetName)
)。
我希望在构建时解析此文件,因此每次读取的 DLL 名称都会进入相应项目的 $(OutputFile)
。
例如,ProjName1.vcxproj
将有以下片段(在构建时):
<Link>
<OutputFile>$(OutDir)DLL1$(TargetExt)</OutputFile>
</Link>
我想,msbuild
的某些功能可以用于此(例如,ReadLinesFromFile task and FindInList task),但我不确定如何将这些部分组合在一起。
有一些此类自动化的示例需要考虑,但我怀疑它们是否与 .vcxproj 格式相关:
- MSBuild ReadLinesFromFile all text on one line
- Read text file and split every line in MSBuild
- Used ReadLinesFromFile to make version in separate file
直接的方法是修改每个 .vcxproj 文件的内容以匹配列表(手动或使用某些脚本)。
还有其他选择吗?
更新 1:我已经设法实现了一个部分解决方案,它基于一个单独的 DLL 名称文件(模块名称) 对于每个项目(有关更多提示,请参阅 Property Functions)。
使用 属性 工作表,在我的情况下很容易 'inject' 修复所有项目:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
...
<PropertyGroup Condition="exists('$(MSBuildProjectDirectory)\_MODULE.name')">
<ModuleName>$([System.IO.File]::ReadAllText('$(MSBuildProjectDirectory)\_MODULE.name'))</ModuleName>
<TargetName>$(ModuleName)</TargetName>
</PropertyGroup>
...
</Project>
虽然效果很好,但该方法不能完全满足我的需求 - 我希望将所有模块名称放在一个文件中。
经过一些调查和尝试,我终于设法为我的案例制定了一个可行的解决方案。基本上它是建立在我之前的部分解决方案之上的,使用了 Regex. The hint how to handle regex in my context was found in another answer to similar question.
的魔力
我还根据自己的喜好调整了列表格式:
DLL1=ProjName1
DLL2=ProjName2
...
我已将更改放在 属性 sheet 中,因此所有相关项目都可以轻松获取它们:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
...
<PropertyGroup Condition="exists('$(MSBuildThisFileDirectory)..\_MODULES.txt')">
<ModulesNames>$([System.IO.File]::ReadAllText('$(MSBuildThisFileDirectory)..\_MODULES.txt'))</ModulesNames>
<ModuleName>$([System.Text.RegularExpressions.Regex]::Match($(ModulesNames), '\W?(\w*)\W?=\W?$(MSBuildProjectName)\W?').get_Groups().get_Item(1))</ModuleName>
<TargetName>$(ModuleName)</TargetName>
</PropertyGroup>
...
</Project>
如果项目未在 _MODULES.txt
中列出,其 $(TargetName)
不受影响。
如果您在项目设置中看到 $(ModuleName)
,则一切都已正确调整:
除了一个小缺点外,该解决方案似乎工作正常:构建系统(VS2017 v.15.9.15)在检测[中的更改方面相当"lazy" =12=] 当解决方案打开时,您必须将其关闭并重新打开。更改列表后很有可能需要重建。
我有一堆用于 VS2017 的 C++ 项目 (.vcxproj),它们生成动态库 (DLL),它们的处理方式类似于 "plugins"(即它们由应用程序动态加载)。
偶尔我想根据文本文件中的某些列表更改生成的 DLL 名称(格式可能会更改):
ProjName1;DLL1
ProjName2;DLL2
...
第一列指定项目名称 ($(ProjectName)
),第二列指定所需的 DLL 名称 ($(TargetName)
)。
我希望在构建时解析此文件,因此每次读取的 DLL 名称都会进入相应项目的 $(OutputFile)
。
例如,ProjName1.vcxproj
将有以下片段(在构建时):
<Link>
<OutputFile>$(OutDir)DLL1$(TargetExt)</OutputFile>
</Link>
我想,msbuild
的某些功能可以用于此(例如,ReadLinesFromFile task and FindInList task),但我不确定如何将这些部分组合在一起。
有一些此类自动化的示例需要考虑,但我怀疑它们是否与 .vcxproj 格式相关:
- MSBuild ReadLinesFromFile all text on one line
- Read text file and split every line in MSBuild
- Used ReadLinesFromFile to make version in separate file
直接的方法是修改每个 .vcxproj 文件的内容以匹配列表(手动或使用某些脚本)。
还有其他选择吗?
更新 1:我已经设法实现了一个部分解决方案,它基于一个单独的 DLL 名称文件(模块名称) 对于每个项目(有关更多提示,请参阅 Property Functions)。
使用 属性 工作表,在我的情况下很容易 'inject' 修复所有项目:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
...
<PropertyGroup Condition="exists('$(MSBuildProjectDirectory)\_MODULE.name')">
<ModuleName>$([System.IO.File]::ReadAllText('$(MSBuildProjectDirectory)\_MODULE.name'))</ModuleName>
<TargetName>$(ModuleName)</TargetName>
</PropertyGroup>
...
</Project>
虽然效果很好,但该方法不能完全满足我的需求 - 我希望将所有模块名称放在一个文件中。
经过一些调查和尝试,我终于设法为我的案例制定了一个可行的解决方案。基本上它是建立在我之前的部分解决方案之上的,使用了 Regex. The hint how to handle regex in my context was found in another answer to similar question.
的魔力我还根据自己的喜好调整了列表格式:
DLL1=ProjName1
DLL2=ProjName2
...
我已将更改放在 属性 sheet 中,因此所有相关项目都可以轻松获取它们:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
...
<PropertyGroup Condition="exists('$(MSBuildThisFileDirectory)..\_MODULES.txt')">
<ModulesNames>$([System.IO.File]::ReadAllText('$(MSBuildThisFileDirectory)..\_MODULES.txt'))</ModulesNames>
<ModuleName>$([System.Text.RegularExpressions.Regex]::Match($(ModulesNames), '\W?(\w*)\W?=\W?$(MSBuildProjectName)\W?').get_Groups().get_Item(1))</ModuleName>
<TargetName>$(ModuleName)</TargetName>
</PropertyGroup>
...
</Project>
如果项目未在 _MODULES.txt
中列出,其 $(TargetName)
不受影响。
如果您在项目设置中看到 $(ModuleName)
,则一切都已正确调整:
除了一个小缺点外,该解决方案似乎工作正常:构建系统(VS2017 v.15.9.15)在检测[中的更改方面相当"lazy" =12=] 当解决方案打开时,您必须将其关闭并重新打开。更改列表后很有可能需要重建。