当我在Visual Studio中创建一个新的项目时,它在fsproj文件中包含以下行。
<Choose>
<When Condition="'$(VisualStudioVersion)' == '11.0'">
<PropertyGroup Condition="Exists('$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets')">
<FSharpTargetsPath>$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets</FSharpTargetsPath>
</PropertyGroup>
</When>
<Otherwise>
<PropertyGroup Condition="Exists('$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets')">
<FSharpTargetsPath>$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets</FSharpTargetsPath>
</PropertyGroup>
</Otherwise>
</Choose>
<Import Project="$(FSharpTargetsPath)" />
在CI服务器上,由于FSharpTargetsPath仍然是空的,所以无法构建。F# 3.1.1的独立安装程序。 在CI服务器上安装了F# 3.1.1的独立安装程序,但没有安装Visual Studio。我需要添加什么才能使之工作?
在我看来,选择子句实际上可能是不正确的。我想应该是 $(VisualStudioVersion)
将是空的''如果没有安装visual studio。然而 $(FSharpTargetsPath)
指向的是我希望独立目标文件所在的地方。显然是把3.0换成了3.1,见下文。
<Choose>
<When Condition="'$(VisualStudioVersion)' == '11.0'">
<PropertyGroup Condition="Exists('$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets')">
<FSharpTargetsPath>$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets</FSharpTargetsPath>
</PropertyGroup>
</When>
<Otherwise>
<PropertyGroup Condition="Exists('$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets')">
<FSharpTargetsPath>$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets</FSharpTargetsPath>
</PropertyGroup>
<PropertyGroup Condition="Exists('$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.1\Framework\v4.0\Microsoft.FSharp.Targets')">
<FSharpTargetsPath>$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.1\Framework\v4.0\Microsoft.FSharp.Targets</FSharpTargetsPath>
</PropertyGroup>
</Otherwise>
</Choose>
免责声明:这纯属猜测,因为我不在电脑上。 这是纯粹的猜测,因为我不在电脑上,我可以尝试这个。
这是3.1.1的安装程序中的一个错误。
小结
这只影响清洁机器的安装。运行底部的脚本,事情就会开始工作,不需要对你的项目进行任何修改。
详细说明
从VS 2013开始,F#项目模板中包含了 Choose
如你在问题中提供的片段。设计如下。
初始检查 VisualStudioVersion = 11.0
是为了支持VS 2012:不管你信不信,只要你的目标是F# 3.0,一个新的VS 2013 F#项目在VS 2012和2013中都能正常打开。 当项目在VS 2012(也就是11.0版本)中打开时,会使用F# 3.0构建目标文件。
展望未来,我们不希望在您的项目文件中硬编码版本号和路径,所以第二种情况代表了未来消费构建目标的机制。这种情况指向一个按VS版本的shim文件,它只包含一个 "真正的 "构建目标文件的导入。 对于VS 2013(也就是12.0版本)。$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets
是3行,只需将真实目标导入在 $(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.1\Framework\v4.0\Microsoft.FSharp.Targets
. 使用这种方法,当一个新的VS版本出现时,你的项目文件不需要更新新的版本和路径。 你的项目会自动找到与你所使用的VS版本相匹配的shim文件,并且这个shim文件会指向那个版本的VS所支持的适当的 "真实 "目标。
除了3.1.1的安装程序错误地将shim文件放在了 "只在检测到VS时才部署 "的桶中,这一切都非常整洁。 所以在一个干净的构建服务器上,虽然 "真正的 "目标文件是 "真正的"。是 安装了(它在 "总是部署 "bucket中),但shim没有安装,所以你会用默认模板进行错误的构建。 :-(
解决办法
完全可以编辑你的项目文件,让它直接消耗真正的目标。这样就可以了。但我想说的是,首选的变通方法是自己创建shim文件。
要自己创建缺失的shim文件(实际上是2个文件,也有一个可移植的),只需在admin powershell提示符下运行以下文件。
$shimDir = "${env:ProgramFiles(x86)}\MSBuild\Microsoft\VisualStudio\v12.0\FSharp"
mkdir $shimDir | out-null
$shimFormat = @'
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.1\Framework\v4.0\Microsoft{0}.FSharp.targets" />
</Project>
'@
'','.Portable' |%{ ($shimFormat -f $_ -split '\n') | out-file "$shimDir\Microsoft$_.FSharp.targets" -encoding ascii }
我的项目需要3.1,所以我去掉了那个选择块,然后在靠近顶部的地方添加了一个FSharpTargetsPath属性,参见 SourceLink.fsproj. 这是我们为FAKE项目所做的一个简单版本,如 FakeLib.fsproj.
<FSharpTargetsPath>$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.1\Framework\v4.0\Microsoft.FSharp.Targets</FSharpTargetsPath>