当我在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仍为空,因此无法构建。 我们在CI服务器上使用新的standalone installer for F# 3.1.1,并且没有安装Visual Studio。 我需要添加什么来使其工作?
答案 0 :(得分:8)
在我看来,choose子句可能实际上是不正确的。如果没有Visual Studio安装,我会认为$(VisualStudioVersion)
将为空。但是,指向的$(FSharpTargetPath)
是我期望独立目标文件驻留的位置。很明显,将3.1换成3.0。见下文。
<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>
免责声明: 这是纯粹的猜测工作,因为我不在PC上,我可以试试这个。
答案 1 :(得分:6)
这是3.1.1安装程序中的错误。
<强>摘要强>
这仅影响清洁机器安装。在底部运行脚本,事情将开始工作,不需要对项目进行任何更改。
<强>详情
从VS 2013开始,F#项目模板包含您在问题中提供的Choose
代码段。设计如下:
对VisualStudioVersion = 11.0
的初步检查是针对VS 2012的反算法支持:不管你信不信,一个新的VS 2013 F#项目将在VS 2012和2013中正常开放,前提是你的目标是F# 3.0。在VS 2012(又称版本11.0)中打开项目时,将使用F#3.0构建目标文件。
展望未来,我们不希望在项目文件中进行硬编码版本号和路径的业务,因此第二种情况代表了消费构建目标的未来机制。此案例指向每个VS版本的填充程序文件,该文件只包含“真实”构建目标文件的导入。对于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版本匹配的填充文件,该填充文件将指向该版本的VS支持的相应“真实”目标。
这是超级neato,除了3.1.1安装程序错误地将shim文件放入“检测到VS时仅部署”桶中。因此,在干净的构建服务器上,虽然安装了“真实”目标文件 (它位于“始终部署”存储桶中),但是垫片不是,并且您使用默认模板获得了破坏的构建。 :-(
解决方法强>
编辑项目文件以便直接消耗真实目标是完全有效的。这会奏效。但我想说首选的解决方法是自己创建填充文件。
要自己创建丢失的填充程序文件(实际上是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 }
答案 2 :(得分:1)
我在项目中要求3.1,所以我删除了选择块,只需在顶部附近添加一个FSharpTargetsPath属性,请参阅SourceLink.fsproj。这是我们为像FakeLib.fsproj这样的FAKE项目所做的更简单的版本。
<FSharpTargetsPath>$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.1\Framework\v4.0\Microsoft.FSharp.Targets</FSharpTargetsPath>