使用F#3.1.1的新独立安装程序时,如何在CI服务器上使用F#

时间:2014-01-23 13:35:43

标签: msbuild f# f#-3.0

当我在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。 我需要添加什么来使其工作?

3 个答案:

答案 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>