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

问题描述 投票:11回答:3

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

msbuild f# f#-3.0
3个回答
8
投票

在我看来,选择子句实际上可能是不正确的。我想应该是 $(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>

免责声明:这纯属猜测,因为我不在电脑上。 这是纯粹的猜测,因为我不在电脑上,我可以尝试这个。


7
投票

这是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 }

1
投票

我的项目需要3.1,所以我去掉了那个选择块,然后在靠近顶部的地方添加了一个FSharpTargetsPath属性,参见 SourceLink.fsproj. 这是我们为FAKE项目所做的一个简单版本,如 FakeLib.fsproj.

<FSharpTargetsPath>$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.1\Framework\v4.0\Microsoft.FSharp.Targets</FSharpTargetsPath>
© www.soinside.com 2019 - 2024. All rights reserved.