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

Msbuild 在使用新的F#3.1.1独立安装程序时,如何在CI服务器上使用F#,msbuild,f#,f#-3.0,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.Ta

在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)" />

$(MSBuildExtensionsPath32)\..\Microsoft SDK\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets
$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets
在CI服务器上,由于FSharpTargetsPath仍然为空,因此不会生成此命令。 我们在CI服务器上使用新的,并且没有安装Visual Studio。
我必须添加什么才能使此工作正常?

在我看来,choose子句实际上可能不正确。如果没有安装visual studio,我认为
$(VisualStudioVersion)
将是空的。但是,指向的
$(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>

$(MSBuildExtensionsPath32)\..\Microsoft SDK\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets
$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets
$(MSBuildExtensionsPath32)\..\Microsoft SDK\F#\3.1\Framework\v4.0\Microsoft.FSharp.Targets

免责声明:这是纯粹的猜测工作,因为我没有在PC上尝试此功能。

这是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 SDK\F\35;\ 3.1\Framework\v4.0\Microsoft.FSharp.Targets
    处的实际目标即可。使用这种方法,当新的VS版本出现时,您的项目文件不需要更新为新版本和路径。您的项目将自动找到与您正在使用的VS的任何版本相匹配的垫片文件,并且该垫片文件将指向该版本的VS中支持的适当的“真实”目标

这就是超级neato,除了3.1.1安装程序错误地将垫片文件放入“仅在检测到VS时部署”存储桶之外。因此,在干净的构建服务器上,虽然安装了“真实”目标文件(它位于“始终部署”存储桶中),但垫片没有安装,并且使用默认模板生成的构建被破坏了:-(

解决方法

编辑项目文件以使其直接使用实际目标是完全有效的。这将起作用。但我认为首选的解决方法是自己创建垫片文件

要自己创建缺少的垫片文件(实际上有两个文件,还有一个可移植的文件),只需从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 }
$shimDir=“${env:ProgramFiles(x86)}\MSBuild\Microsoft\VisualStudio\v12.0\FSharp”
mkdir$shimDir |输出为空
$shimFormat=@'
'@
''.'.Portable'.%{($shimFormat-f$.-split'\n')|输出文件“$shimDir\Microsoft$.\ FSharp.targets”-编码ascii}

我在我的项目中需要3.1,所以我删除了choose块,只需在顶部附近添加一个FSharpTargetsPath属性,请参见。这是我们为类似的伪项目所做的更简单的版本

$(MSBuildExtensionsPath32)\..\Microsoft SDK\F\35;\ 3.1\Framework\v4.0\Microsoft.FSharp.Targets

感谢您的详细回答。“首选解决方案”的问题我真的没有访问CI服务器的权限。我所能做的就是希望管理员安装安装程序。即使有了这个修复,我在mono上也有同样的问题。谢谢!这对我是一个很大的帮助。我想使用FAKE时使用3.0,使用VS 2012时使用3.0,使用VS 2013时使用3.1,我想我已经用这些指令解决了。锚定路径s使用
$(MSBuildExtensionsPath32)\..
访问C:\Program Files(x86)已成为构建的定时炸弹,因为该变量是C:\Program Files(x86)\VS2017中的Microsoft Visual Studio\2017\BuildTools\MSBuild,以及类似的MSBuild 15。Microsoft.FSharp.targets文件似乎也经常移动。我的问题是缺少一个F#编译器…它是从Visual Studio安装程序安装的,现在一切正常。
<FSharpTargetsPath>$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.1\Framework\v4.0\Microsoft.FSharp.Targets</FSharpTargetsPath>