我有一个解决方案文件 (MySolution.sln),其中包含一个项目 (MyProject.vcxproj)。我想通过解决方案在我的项目上执行自定义目标 (MyCustomTarget)。它看起来像这样:
msbuild MySolution.sln /t:MyCustomTarget
当我执行命令时,我会收到一条错误消息:
MySolution.sln.metaproj:错误 MSB4057:项目中不存在目标“MyCustomTarget”。 [MySolution.sln]
您可以使用 Microsoft.Cpp.Win32.targets 中的任何标准目标(例如:ClCompile、Link)或从 MyProject.vcxproj 中的 .targets 文件中选择的任何其他目标替换 MyCustomTarget。他们都不会工作。
当环境变量 msbuildemitsolution 设置为 1 时,我可以检查生成的 MySolution.sln.metaproj 文件。在底部指定了 4 个目标:构建、重建、清理和发布。使用这些目标而不是 MyCustomTarget,项目构建正常。此外,如果我指定项目文件而不是解决方案文件,它也会构建:
msbuild MyProject.vcxproj /t:MyCustomTarget
但是使用这种格式,我将失去 OutDir 属性,必须手动设置配置和平台,因此我失去了拥有解决方案文件的好处。
有什么方法可以将我的自定义目标与我最初打算的解决方案文件一起使用吗?
据我了解,问题是 msbuild 生成了这个中间项目文件 (mysolution.sln.metproj),但它将从 MyProject.vcxproj 中导入,包括 .targets 文件。难怪 MyCustomTarget 不被识别。
我目前的解决方法是将项目文件与 msbuild 一起使用,并尽量不要错过解决方案文件中的任何内容:
msbuild MyProject.vcxproj /t:MyCustomTarget /p:Configuration=MyConfig;Platform=MyPlatform;OutDir=MySolution\Platform_MyConfig\
但这不是一个合适的解决方案,不灵活,容易出错,并且不会自动适应解决方案文件中的更改。
最佳答案
我想你已经回答了你的问题。答案是不。 .sln.metaproj 文件中没有名为“MyCustomTarget”的目标,因此 MSBuild 会为您提供该错误消息。
现在,解决您在命令行上传递额外参数的问题。如果您在 .vcxproj 文件中设置默认值,则不需要传递平台和配置。在导入任何标准目标文件之前,将其添加到项目文件中的某处:
<Platform Condition="'$(Platform)'==''">MyPlatform</Platform>
<Configuration Condition="'$(Configuration)'==''">MyConfiguration</Configuration>
解决方案中所有项目共享的 OutDir 配置可以这样完成。我将假设您的解决方案的结构使 .sln 文件位于根文件夹中,并且所有项目都位于根目录下的子文件夹(任意深度)中,或者与解决方案位于同一文件夹中。如果不是这种情况,您将不得不稍微调整代码以适应您的情况。
在项目中定义平台和配置后,立即添加此属性组:
<PropertyGroup>
<RootFolder>$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory),MySolutionName.sln))</RootFolder>
<OutDir Condition="'$(OutDir)'==''">$(RootFolder)\$(Platform)_$(Configuration)</OutDir>
</PropertyGroup>
上面的代码遵循您将 OutDir 设置为
MySolution\MyPlatform_MyConfiguration
的约定.所有这些方法的缺点是您必须手动修改解决方案中的所有项目。但是,它将在 future 为您提供很大的灵活性。例如,所有项目中共享的任何通用设置都可以提取到单个 .props 文件中
<Import>
到每个项目中,因此可以在一个地方完成对配置的更改。
关于msbuild - 在解决方案文件上调用自定义 MSBuild 目标,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23910389/