diff --git a/.gitignore b/.gitignore index 1a7e530e494..a4c90c19878 100644 --- a/.gitignore +++ b/.gitignore @@ -121,3 +121,6 @@ tests/fsharpqa/testenv/bin/System.ValueTuple.dll */.fake /fcs/packages/ */paket-files/ +/fcs/TestResult.xml +/tests/fcs/ +/fcs/.paket/Paket.Restore.targets diff --git a/build.cmd b/build.cmd index b24937a8647..7431a36c19e 100644 --- a/build.cmd +++ b/build.cmd @@ -538,10 +538,16 @@ set _ngenexe="%SystemRoot%\Microsoft.NET\Framework\v4.0.30319\ngen.exe" if not exist %_ngenexe% echo Error: Could not find ngen.exe. && goto :failure echo ---------------- Done with prepare, starting package restore ---------------- + set _nugetexe="%~dp0.nuget\NuGet.exe" set _nugetconfig="%~dp0.nuget\NuGet.Config" if "%RestorePackages%" == "true" ( + cd fcs + .paket\paket.exe restore + cd.. + @if ERRORLEVEL 1 echo Error: Paket restore failed && goto :failure + %_ngenexe% install %_nugetexe% /nologo %_nugetexe% restore packages.config -PackagesDirectory packages -ConfigFile %_nugetconfig% diff --git a/build.sh b/build.sh index 6c3323a4f9b..561a129c522 100755 --- a/build.sh +++ b/build.sh @@ -412,6 +412,14 @@ _nugetconfig=".nuget/NuGet.Config" # Restore packages (default to restoring packages if otherwise unspecified). if [ "${RestorePackages:-true}" = 'true' ]; then + cd fcs + mono .paket/paket.exe restore + cd .. + exit_code=$? + if [ $exit_code -ne 0 ]; then + exit $exit_code + fi + eval "$_nugetexe restore packages.config -PackagesDirectory packages -ConfigFile $_nugetconfig" if [ $? -ne 0 ]; then failwith "Nuget restore failed" diff --git a/fcs/.paket/Paket.Restore.targets b/fcs/.paket/Paket.Restore.targets deleted file mode 100644 index 67f745a3671..00000000000 --- a/fcs/.paket/Paket.Restore.targets +++ /dev/null @@ -1,225 +0,0 @@ - - - - - - - $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - - true - $(MSBuildThisFileDirectory) - $(MSBuildThisFileDirectory)..\ - $(PaketRootPath)paket-files\paket.restore.cached - $(PaketRootPath)paket.lock - /Library/Frameworks/Mono.framework/Commands/mono - mono - - $(PaketRootPath)paket.exe - $(PaketToolsPath)paket.exe - "$(PaketExePath)" - $(MonoPath) --runtime=v4.0.30319 "$(PaketExePath)" - $(PaketRootPath)paket.bootstrapper.exe - $(PaketToolsPath)paket.bootstrapper.exe - "$(PaketBootStrapperExePath)" - $(MonoPath) --runtime=v4.0.30319 "$(PaketBootStrapperExePath)" - - - - - true - true - - - - - - - true - $(NoWarn);NU1603 - - - - $([System.IO.File]::ReadAllText('$(PaketRestoreCacheFile)')) - $([System.IO.File]::ReadAllText('$(PaketLockFilePath)')) - true - false - true - - - - - - - - - $(MSBuildProjectDirectory)\obj\$(MSBuildProjectFile).paket.references.cached - - $(MSBuildProjectFullPath).paket.references - - $(MSBuildProjectDirectory)\$(MSBuildProjectName).paket.references - - $(MSBuildProjectDirectory)\paket.references - $(MSBuildProjectDirectory)\obj\$(MSBuildProjectFile).$(TargetFramework).paket.resolved - true - references-file-or-cache-not-found - - - - - $([System.IO.File]::ReadAllText('$(PaketReferencesCachedFilePath)')) - $([System.IO.File]::ReadAllText('$(PaketOriginalReferencesFilePath)')) - references-file - false - - - - - false - - - - - true - target-framework '$(TargetFramework)' - - - - - - - - - - - - - - - - - $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[0]) - $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[1]) - - - %(PaketReferencesFileLinesInfo.PackageVersion) - - - - - $(MSBuildProjectDirectory)/obj/$(MSBuildProjectFile).NuGet.Config - - - - - - - false - - - - - - $(MSBuildProjectDirectory)/$(MSBuildProjectFile) - true - false - true - - - - <_NuspecFiles Include="$(BaseIntermediateOutputPath)*.nuspec"/> - - - - - - - - - - - - - - - diff --git a/fcs/FSharp.Compiler.Service.MSBuild.v12/FSharp.Compiler.Service.MSBuild.v12.fsproj b/fcs/FSharp.Compiler.Service.MSBuild.v12/FSharp.Compiler.Service.MSBuild.v12.fsproj index e929138c567..f66cda2f775 100644 --- a/fcs/FSharp.Compiler.Service.MSBuild.v12/FSharp.Compiler.Service.MSBuild.v12.fsproj +++ b/fcs/FSharp.Compiler.Service.MSBuild.v12/FSharp.Compiler.Service.MSBuild.v12.fsproj @@ -89,4 +89,4 @@ - \ No newline at end of file + diff --git a/fcs/FSharp.Compiler.Service.ProjectCracker/ProjectCracker.fs b/fcs/FSharp.Compiler.Service.ProjectCracker/ProjectCracker.fs index 45fab18685b..7a36085de06 100644 --- a/fcs/FSharp.Compiler.Service.ProjectCracker/ProjectCracker.fs +++ b/fcs/FSharp.Compiler.Service.ProjectCracker/ProjectCracker.fs @@ -8,18 +8,17 @@ open System.Diagnostics open System.Text open System.IO open System +open System.Xml -type ProjectCracker = - static member GetProjectOptionsFromProjectFileLogged(projectFileName : string, ?properties : (string * string) list, ?loadedTimeStamp, ?enableLogging) = - let loadedTimeStamp = defaultArg loadedTimeStamp DateTime.MaxValue // Not 'now', we don't want to force reloading - let properties = defaultArg properties [] - let enableLogging = defaultArg enableLogging true +module Utils = + + let Convert loadedTimeStamp (originalOpts: ProjectCrackerTool.ProjectOptions) = let logMap = ref Map.empty - let rec convert (opts: ProjectCrackerTool.ProjectOptions) : FSharpProjectOptions = + let rec convertProject (opts: ProjectCrackerTool.ProjectOptions) = if not (isNull opts.Error) then failwith opts.Error - let referencedProjects = Array.map (fun (a, b) -> a, convert b) opts.ReferencedProjectOptions + let referencedProjects() = Array.map (fun (a, b) -> a,convertProject b) opts.ReferencedProjectOptions let sourceFiles, otherOptions = opts.Options @@ -41,7 +40,7 @@ type ProjectCracker = { ProjectFileName = opts.ProjectFile SourceFiles = sourceFiles OtherOptions = otherOptions - ReferencedProjects = referencedProjects + ReferencedProjects = referencedProjects() IsIncompleteTypeCheckEnvironment = false UseScriptResolutionRules = false LoadTime = loadedTimeStamp @@ -50,6 +49,16 @@ type ProjectCracker = ExtraProjectInfo = None Stamp = None } + convertProject originalOpts, !logMap + +type ProjectCracker = + + static member GetProjectOptionsFromProjectFileLogged(projectFileName : string, ?properties : (string * string) list, ?loadedTimeStamp, ?enableLogging) = + let loadedTimeStamp = defaultArg loadedTimeStamp DateTime.MaxValue // Not 'now', we don't want to force reloading + let properties = defaultArg properties [] + let enableLogging = defaultArg enableLogging true + + #if NETSTANDARD1_6 let arguments = [| yield projectFileName @@ -70,20 +79,47 @@ type ProjectCracker = let codebase = Path.GetDirectoryName(Uri(typeof.Assembly.CodeBase).LocalPath) let crackerFilename = Path.Combine(codebase,"FSharp.Compiler.Service.ProjectCrackerTool.exe") - if not (File.Exists crackerFilename) then failwithf "ProjectCracker exe not found at: %s it must be next to the ProjectCracker dll." crackerFilename + if not (File.Exists crackerFilename) then + failwithf "ProjectCracker exe not found at: %s it must be next to the ProjectCracker dll." crackerFilename + let p = new System.Diagnostics.Process() + p.StartInfo.FileName <- crackerFilename p.StartInfo.Arguments <- arguments.ToString() p.StartInfo.UseShellExecute <- false p.StartInfo.CreateNoWindow <- true p.StartInfo.RedirectStandardOutput <- true + p.StartInfo.RedirectStandardError <- true + + let sbOut = StringBuilder() + let sbErr = StringBuilder() + + p.ErrorDataReceived.AddHandler(fun _ a -> sbErr.AppendLine a.Data |> ignore) + p.OutputDataReceived.AddHandler(fun _ a -> sbOut.AppendLine a.Data |> ignore) + ignore <| p.Start() - let ser = new DataContractJsonSerializer(typeof) - let opts = ser.ReadObject(p.StandardOutput.BaseStream) :?> ProjectCrackerTool.ProjectOptions + p.EnableRaisingEvents <- true + p.BeginOutputReadLine() + p.BeginErrorReadLine() + + p.WaitForExit() + + let crackerOut = sbOut.ToString() + let crackerErr = sbErr.ToString() + + let opts = + try + let ser = new DataContractJsonSerializer(typeof) + let stringBytes = Encoding.Unicode.GetBytes crackerOut + use ms = new MemoryStream(stringBytes) + ser.ReadObject(ms) :?> ProjectCrackerTool.ProjectOptions + with + exn -> + raise (Exception(sprintf "error parsing ProjectCrackerTool output, stdoutput was:\n%s\n\nstderr was:\n%s" crackerOut crackerErr, exn)) #endif - convert opts, !logMap + Utils.Convert loadedTimeStamp opts static member GetProjectOptionsFromProjectFile(projectFileName : string, ?properties : (string * string) list, ?loadedTimeStamp) = fst (ProjectCracker.GetProjectOptionsFromProjectFileLogged( diff --git a/fcs/FSharp.Compiler.Service.ProjectCrackerTool/FSharp.Compiler.Service.ProjectCrackerTool.fsproj b/fcs/FSharp.Compiler.Service.ProjectCrackerTool/FSharp.Compiler.Service.ProjectCrackerTool.fsproj index 07bae7e5765..66d196a1d54 100644 --- a/fcs/FSharp.Compiler.Service.ProjectCrackerTool/FSharp.Compiler.Service.ProjectCrackerTool.fsproj +++ b/fcs/FSharp.Compiler.Service.ProjectCrackerTool/FSharp.Compiler.Service.ProjectCrackerTool.fsproj @@ -46,24 +46,9 @@ + - - $(FSharpSourcesRoot)/../fcs/dependencies/MSBuild.v14.0/Microsoft.Build.Framework.dll - false - - - $(FSharpSourcesRoot)/../fcs/dependencies/MSBuild.v14.0/Microsoft.Build.Engine.dll - false - - - $(FSharpSourcesRoot)/../fcs/dependencies/MSBuild.v14.0/Microsoft.Build.dll - false - - - $(FSharpSourcesRoot)/../fcs/dependencies/MSBuild.v12.0/Microsoft.Build.Utilities.v12.0.dll - false - @@ -71,13 +56,75 @@ - $(FSharpSourcesRoot)\..\packages\Microsoft.Portable.FSharp.Core.4.1.20\lib\profiles\net40\FSharp.Core.dll false - + + + + + ..\packages\Microsoft.Build\lib\net45\Microsoft.Build.dll + True + True + + + + + + + + + ..\packages\Microsoft.Build.Engine\lib\net45\Microsoft.Build.Engine.dll + True + True + + + + + + + + + ..\packages\Microsoft.Build.Framework\lib\net45\Microsoft.Build.Framework.dll + True + True + + + + + + + + + ..\packages\Microsoft.Build.Utilities.Core\lib\net45\Microsoft.Build.Utilities.Core.dll + True + True + + + + + + + + + True + + + + + + + + + ..\packages\System.Threading.Tasks.Dataflow\lib\portable-net45+win8+wpa81\System.Threading.Tasks.Dataflow.dll + True + True + + + + \ No newline at end of file diff --git a/fcs/FSharp.Compiler.Service.ProjectCrackerTool/Program.fs b/fcs/FSharp.Compiler.Service.ProjectCrackerTool/Program.fs index ed8a8b15992..7ce360c312f 100644 --- a/fcs/FSharp.Compiler.Service.ProjectCrackerTool/Program.fs +++ b/fcs/FSharp.Compiler.Service.ProjectCrackerTool/Program.fs @@ -1,21 +1,46 @@ namespace Microsoft.FSharp.Compiler.SourceCodeServices.ProjectCrackerTool open System -open System.IO +open System.Reflection open System.Runtime.Serialization.Json module Program = - [] - let main argv = - let text = Array.exists (fun (s: string) -> s = "--text") argv - let argv = Array.filter (fun (s: string) -> s <> "--text") argv +#if !DOTNETCORE + let addMSBuildv14BackupResolution () = + let onResolveEvent = new ResolveEventHandler(fun sender evArgs -> + let requestedAssembly = AssemblyName(evArgs.Name) + if requestedAssembly.Name.StartsWith("Microsoft.Build") && + not (requestedAssembly.Name.EndsWith(".resources")) && + not (requestedAssembly.Version.ToString().Contains("12.0.0.0")) + then + // If the version of MSBuild that we're using wasn't present on the machine, then + // just revert back to 12.0.0.0 since that's normally installed as part of the .NET + // Framework. + requestedAssembly.Version <- Version("12.0.0.0") + Assembly.Load requestedAssembly + else + null) + AppDomain.CurrentDomain.add_AssemblyResolve(onResolveEvent) +#endif + let crackAndSendOutput asText argv = let ret, opts = ProjectCrackerTool.crackOpen argv - if text then + if asText then printfn "%A" opts else let ser = new DataContractJsonSerializer(typeof) ser.WriteObject(Console.OpenStandardOutput(), opts) ret + + + [][] + let main argv = + let asText = Array.exists (fun (s: string) -> s = "--text") argv + let argv = Array.filter (fun (s: string) -> s <> "--text") argv + +#if !DOTNETCORE + addMSBuildv14BackupResolution () +#endif + crackAndSendOutput asText argv diff --git a/fcs/FSharp.Compiler.Service.ProjectCrackerTool/ProjectCrackerTool.fs b/fcs/FSharp.Compiler.Service.ProjectCrackerTool/ProjectCrackerTool.fs index 9be9c375370..a20c7a33c0e 100644 --- a/fcs/FSharp.Compiler.Service.ProjectCrackerTool/ProjectCrackerTool.fs +++ b/fcs/FSharp.Compiler.Service.ProjectCrackerTool/ProjectCrackerTool.fs @@ -2,12 +2,13 @@ open System open System.IO -open System.Reflection open System.Text open Microsoft.Build.Framework open Microsoft.Build.Utilities module internal ProjectCrackerTool = + open System.Collections.Generic + open Microsoft.Build.Evaluation let runningOnMono = #if DOTNETCORE @@ -36,17 +37,159 @@ module internal ProjectCrackerTool = member th.Compile(_:obj, _:obj, _:obj) = 0 interface ITaskHost + let vs = + let programFiles = + let getEnv v = + let result = System.Environment.GetEnvironmentVariable(v) + match result with + | null -> None + | _ -> Some result + + match List.tryPick getEnv [ "ProgramFiles(x86)"; "ProgramFiles" ] with + | Some r -> r + | None -> "C:\\Program Files (x86)" + + let vsVersions = ["14.0"; "12.0"] + let msbuildBin v = IO.Path.Combine(programFiles, "MSBuild", v, "Bin", "MSBuild.exe") + List.tryFind (fun v -> IO.File.Exists(msbuildBin v)) vsVersions + + let mkAbsolute dir v = + if Path.IsPathRooted v then v + else Path.Combine(dir, v) + + let mkAbsoluteOpt dir v = Option.map (mkAbsolute dir) v + + let CrackProjectUsingNewBuildAPI fsprojFile properties logOpt = + let fsprojFullPath = try Path.GetFullPath(fsprojFile) with _ -> fsprojFile + let fsprojAbsDirectory = Path.GetDirectoryName fsprojFullPath + + use _pwd = + let dir = Directory.GetCurrentDirectory() + Directory.SetCurrentDirectory(fsprojAbsDirectory) + { new System.IDisposable with + member x.Dispose() = Directory.SetCurrentDirectory(dir) } + use engine = new Microsoft.Build.Evaluation.ProjectCollection() + let host = new HostCompile() + + engine.HostServices.RegisterHostObject(fsprojFullPath, "CoreCompile", "Fsc", host) + + let projectInstanceFromFullPath (fsprojFullPath: string) = + use file = new FileStream(fsprojFullPath, FileMode.Open, FileAccess.Read, FileShare.Read) + use stream = new StreamReader(file) + use xmlReader = System.Xml.XmlReader.Create(stream) + + let project = + try + engine.LoadProject(xmlReader, FullPath=fsprojFullPath) + with + | exn -> + let tools = engine.Toolsets |> Seq.map (fun x -> x.ToolsPath) |> Seq.toList + raise (new Exception(sprintf "Could not load project %s in ProjectCollection. Available tools: %A. Message: %s" fsprojFullPath tools exn.Message)) + + project.SetGlobalProperty("BuildingInsideVisualStudio", "true") |> ignore + if not (List.exists (fun (p,_) -> p = "VisualStudioVersion") properties) then + match vs with + | Some version -> project.SetGlobalProperty("VisualStudioVersion", version) |> ignore + | None -> () + project.SetGlobalProperty("ShouldUnsetParentConfigurationAndPlatform", "false") |> ignore + for (prop, value) in properties do + project.SetGlobalProperty(prop, value) |> ignore + + project.CreateProjectInstance() + + let project = projectInstanceFromFullPath fsprojFullPath + let directory = project.Directory + + let getprop (p: Microsoft.Build.Execution.ProjectInstance) s = + let v = p.GetPropertyValue s + if String.IsNullOrWhiteSpace v then None + else Some v + + let outFileOpt = getprop project "TargetPath" + + let log = match logOpt with + | None -> [] + | Some l -> [l :> ILogger] + + project.Build([| "Build" |], log) |> ignore + + let getItems s = [ for f in project.GetItems(s) -> mkAbsolute directory f.EvaluatedInclude ] + + let projectReferences = + [ for cp in project.GetItems("ProjectReference") do + yield cp.GetMetadataValue("FullPath") + ] + + let references = + [ for i in project.GetItems("ReferencePath") do + yield i.EvaluatedInclude + for i in project.GetItems("ChildProjectReferences") do + yield i.EvaluatedInclude ] + + outFileOpt, directory, getItems, references, projectReferences, getprop project, project.FullPath + +#if !DOTNETCORE + let CrackProjectUsingOldBuildAPI (fsprojFile:string) properties logOpt = + let engine = new Microsoft.Build.BuildEngine.Engine() + Option.iter (fun l -> engine.RegisterLogger(l)) logOpt + + let bpg = Microsoft.Build.BuildEngine.BuildPropertyGroup() + + bpg.SetProperty("BuildingInsideVisualStudio", "true") + for (prop, value) in properties do + bpg.SetProperty(prop, value) + + engine.GlobalProperties <- bpg + + let projectFromFile (fsprojFile:string) = + // We seem to need to pass 12.0/4.0 in here for some unknown reason + let project = new Microsoft.Build.BuildEngine.Project(engine, engine.DefaultToolsVersion) + do project.Load(fsprojFile) + project + + let project = projectFromFile fsprojFile + project.Build([| "ResolveReferences" |]) |> ignore + let directory = Path.GetDirectoryName project.FullFileName + + let getProp (p: Microsoft.Build.BuildEngine.Project) s = + let v = p.GetEvaluatedProperty s + if String.IsNullOrWhiteSpace v then None + else Some v + + let outFileOpt = + match mkAbsoluteOpt directory (getProp project "OutDir") with + | None -> None + | Some d -> mkAbsoluteOpt d (getProp project "TargetFileName") + + let getItems s = + let fs = project.GetEvaluatedItemsByName(s) + [ for f in fs -> mkAbsolute directory f.FinalItemSpec ] + + let projectReferences = + [ for i in project.GetEvaluatedItemsByName("ProjectReference") do + yield mkAbsolute directory i.FinalItemSpec + ] + + let references = + [ for i in project.GetEvaluatedItemsByName("ReferencePath") do + yield i.FinalItemSpec + for i in project.GetEvaluatedItemsByName("ChildProjectReferences") do + yield i.FinalItemSpec ] + // Duplicate slashes sometimes appear in the output here, which prevents + // them from matching keys used in FSharpProjectOptions.ReferencedProjects + |> List.map (fun (s: string) -> s.Replace("//","/")) + + outFileOpt, directory, getItems, references, projectReferences, getProp project, project.FullFileName + +#endif + //---------------------------------------------------------------------------- // FSharpProjectFileInfo // [] type FSharpProjectFileInfo (fsprojFileName:string, ?properties, ?enableLogging) = - let properties = defaultArg properties [] let enableLogging = defaultArg enableLogging false - let mkAbsolute dir v = - if Path.IsPathRooted v then v - else Path.Combine(dir, v) let logOpt = if enableLogging then @@ -55,152 +198,17 @@ module internal ProjectCrackerTool = Some log else None - -#if !DOTNETCORE - let mkAbsoluteOpt dir v = Option.map (mkAbsolute dir) v - - let CrackProjectUsingOldBuildAPI(fsprojFile:string) = - let engine = new Microsoft.Build.BuildEngine.Engine() - Option.iter (fun l -> engine.RegisterLogger(l)) logOpt - - let bpg = Microsoft.Build.BuildEngine.BuildPropertyGroup() - - bpg.SetProperty("BuildingInsideVisualStudio", "true") - for (prop, value) in properties do - bpg.SetProperty(prop, value) - - engine.GlobalProperties <- bpg - - let projectFromFile (fsprojFile:string) = - // We seem to need to pass 12.0/4.0 in here for some unknown reason - let project = new Microsoft.Build.BuildEngine.Project(engine, engine.DefaultToolsVersion) - do project.Load(fsprojFile) - project - - let project = projectFromFile fsprojFile - project.Build([| "ResolveReferences" |]) |> ignore - let directory = Path.GetDirectoryName project.FullFileName - - let getProp (p: Microsoft.Build.BuildEngine.Project) s = - let v = p.GetEvaluatedProperty s - if String.IsNullOrWhiteSpace v then None - else Some v - - let outFileOpt = - match mkAbsoluteOpt directory (getProp project "OutDir") with - | None -> None - | Some d -> mkAbsoluteOpt d (getProp project "TargetFileName") - - let getItems s = - let fs = project.GetEvaluatedItemsByName(s) - [ for f in fs -> mkAbsolute directory f.FinalItemSpec ] - - let projectReferences = - [ for i in project.GetEvaluatedItemsByName("ProjectReference") do - yield mkAbsolute directory i.FinalItemSpec - ] - - let references = - [ for i in project.GetEvaluatedItemsByName("ReferencePath") do - yield i.FinalItemSpec - for i in project.GetEvaluatedItemsByName("ChildProjectReferences") do - yield i.FinalItemSpec ] - // Duplicate slashes sometimes appear in the output here, which prevents - // them from matching keys used in FSharpProjectOptions.ReferencedProjects - |> List.map (fun (s: string) -> s.Replace("//","/")) - - outFileOpt, directory, getItems, references, projectReferences, getProp project, project.FullFileName -#endif - - let vs = - let programFiles = - let getEnv v = - let result = System.Environment.GetEnvironmentVariable(v) - match result with - | null -> None - | _ -> Some result - - match List.tryPick getEnv [ "ProgramFiles(x86)"; "ProgramFiles" ] with - | Some r -> r - | None -> "C:\\Program Files (x86)" - - let vsVersions = ["14.0"; "12.0"] - let msbuildBin v = IO.Path.Combine(programFiles, "MSBuild", v, "Bin", "MSBuild.exe") - List.tryFind (fun v -> IO.File.Exists(msbuildBin v)) vsVersions - - let CrackProjectUsingNewBuildAPI(fsprojFile) = - let fsprojFullPath = try Path.GetFullPath(fsprojFile) with _ -> fsprojFile - let fsprojAbsDirectory = Path.GetDirectoryName fsprojFullPath - - use _pwd = - let dir = Directory.GetCurrentDirectory() - Directory.SetCurrentDirectory(fsprojAbsDirectory) - { new System.IDisposable with - member x.Dispose() = Directory.SetCurrentDirectory(dir) } - use engine = new Microsoft.Build.Evaluation.ProjectCollection() - let host = new HostCompile() - engine.HostServices.RegisterHostObject(fsprojFullPath, "CoreCompile", "Fsc", host) - - - let projectInstanceFromFullPath (fsprojFullPath: string) = - use file = new FileStream(fsprojFullPath, FileMode.Open, FileAccess.Read, FileShare.Read) - use stream = new StreamReader(file) - use xmlReader = System.Xml.XmlReader.Create(stream) - - let project = engine.LoadProject(xmlReader, FullPath=fsprojFullPath) - - project.SetGlobalProperty("BuildingInsideVisualStudio", "true") |> ignore - if not (List.exists (fun (p,_) -> p = "VisualStudioVersion") properties) then - match vs with - | Some version -> project.SetGlobalProperty("VisualStudioVersion", version) |> ignore - | None -> () - project.SetGlobalProperty("ShouldUnsetParentConfigurationAndPlatform", "false") |> ignore - for (prop, value) in properties do - project.SetGlobalProperty(prop, value) |> ignore - - project.CreateProjectInstance() - - let project = projectInstanceFromFullPath fsprojFullPath - let directory = project.Directory - - let getprop (p: Microsoft.Build.Execution.ProjectInstance) s = - let v = p.GetPropertyValue s - if String.IsNullOrWhiteSpace v then None - else Some v - - let outFileOpt = getprop project "TargetPath" - - let log = match logOpt with - | None -> [] - | Some l -> [l :> ILogger] - - project.Build([| "Build" |], log) |> ignore - - let getItems s = [ for f in project.GetItems(s) -> mkAbsolute directory f.EvaluatedInclude ] - - let projectReferences = - [ for cp in project.GetItems("ProjectReference") do - yield cp.GetMetadataValue("FullPath") - ] - - let references = - [ for i in project.GetItems("ReferencePath") do - yield i.EvaluatedInclude - for i in project.GetItems("ChildProjectReferences") do - yield i.EvaluatedInclude ] - - outFileOpt, directory, getItems, references, projectReferences, getprop project, project.FullPath - + let outFileOpt, directory, getItems, references, projectReferences, getProp, fsprojFullPath = try #if DOTNETCORE - CrackProjectUsingNewBuildAPI(fsprojFileName) + CrackProjectUsingNewBuildAPI fsprojFileName properties logOpt with #else if runningOnMono then - CrackProjectUsingOldBuildAPI(fsprojFileName) + CrackProjectUsingOldBuildAPI fsprojFileName properties logOpt else - CrackProjectUsingNewBuildAPI(fsprojFileName) + CrackProjectUsingNewBuildAPI fsprojFileName properties logOpt with | :? Microsoft.Build.BuildEngine.InvalidProjectFileException as e -> raise (Microsoft.Build.Exceptions.InvalidProjectFileException( @@ -384,66 +392,57 @@ module internal ProjectCrackerTool = static member Parse(fsprojFileName:string, ?properties, ?enableLogging) = new FSharpProjectFileInfo(fsprojFileName, ?properties=properties, ?enableLogging=enableLogging) let getOptions file enableLogging properties = + let cache = new Dictionary<_,_>() let rec getOptions file : Option * ProjectOptions = - let parsedProject = FSharpProjectFileInfo.Parse(file, properties=properties, enableLogging=enableLogging) - let referencedProjectOptions = - [| for file in parsedProject.ProjectReferences do - if Path.GetExtension(file) = ".fsproj" then - match getOptions file with - | Some outFile, opts -> yield outFile, opts - | None, _ -> () |] - - // Workaround for Mono 4.2, which doesn't populate the subproject - // details anymore outside of a solution context. See https://github.com/mono/mono/commit/76c6a08e730393927b6851709cdae1d397cbcc3a#diff-59afd196a55d61d5d1eaaef7bd49d1e5 - // and some explanation from the author at https://github.com/fsharp/FSharp.Compiler.Service/pull/455#issuecomment-154103963 - // - // In particular we want the output path, which we can get from - // fully parsing that project itself. We also have to specially parse - // C# referenced projects, as we don't look at them otherwise. - let referencedProjectOutputs = - if runningOnMono then - [ yield! Array.map (fun (s,_) -> "-r:" + s) referencedProjectOptions - for file in parsedProject.ProjectReferences do - let ext = Path.GetExtension(file) - if ext = ".csproj" || ext = ".vbproj" then - let parsedProject = FSharpProjectFileInfo.Parse(file, properties=properties, enableLogging=false) - match parsedProject.OutputFile with - | None -> () - | Some f -> yield "-r:" + f ] - else - [] - - // On some versions of Mono the referenced projects are already - // correctly included, so we make sure not to introduce duplicates - |> List.filter (fun r -> not (Set.contains r (set parsedProject.Options))) - - let options = { ProjectFile = file - Options = Array.ofSeq (parsedProject.Options @ referencedProjectOutputs) - ReferencedProjectOptions = referencedProjectOptions - LogOutput = parsedProject.LogOutput - Error = null } - - parsedProject.OutputFile, options + match cache.TryGetValue file with + | true, option -> option + | _ -> + let parsedProject = FSharpProjectFileInfo.Parse(file, properties=properties, enableLogging=enableLogging) + + let referencedProjectOptions = + [| for file in parsedProject.ProjectReferences do + if Path.GetExtension(file) = ".fsproj" then + match getOptions file with + | Some outFile, opts -> yield outFile, opts + | None, _ -> () |] + + // Workaround for Mono 4.2, which doesn't populate the subproject + // details anymore outside of a solution context. See https://github.com/mono/mono/commit/76c6a08e730393927b6851709cdae1d397cbcc3a#diff-59afd196a55d61d5d1eaaef7bd49d1e5 + // and some explanation from the author at https://github.com/fsharp/FSharp.Compiler.Service/pull/455#issuecomment-154103963 + // + // In particular we want the output path, which we can get from + // fully parsing that project itself. We also have to specially parse + // C# referenced projects, as we don't look at them otherwise. + let referencedProjectOutputs = + if runningOnMono then + [ yield! Array.map (fun (s,_) -> "-r:" + s) referencedProjectOptions + for file in parsedProject.ProjectReferences do + let ext = Path.GetExtension(file) + if ext = ".csproj" || ext = ".vbproj" then + let parsedProject = FSharpProjectFileInfo.Parse(file, properties=properties, enableLogging=false) + match parsedProject.OutputFile with + | None -> () + | Some f -> yield "-r:" + f ] + else + [] + + // On some versions of Mono the referenced projects are already + // correctly included, so we make sure not to introduce duplicates + |> List.filter (fun r -> not (Set.contains r (set parsedProject.Options))) + + let options = { ProjectFile = file + Options = Array.ofSeq (parsedProject.Options @ referencedProjectOutputs) + ReferencedProjectOptions = referencedProjectOptions + LogOutput = parsedProject.LogOutput + Error = null } + + let result = parsedProject.OutputFile, options + cache.Add(file,result) + result snd (getOptions file) -#if !DOTNETCORE - let addMSBuildv14BackupResolution () = - let onResolveEvent = new ResolveEventHandler(fun sender evArgs -> - let requestedAssembly = AssemblyName(evArgs.Name) - if requestedAssembly.Name.StartsWith("Microsoft.Build") && - not (requestedAssembly.Name.EndsWith(".resources")) && - not (requestedAssembly.Version.ToString().Contains("12.0.0.0")) then - // If the version of MSBuild that we're using wasn't present on the machine, then - // just revert back to 12.0.0.0 since that's normally installed as part of the .NET - // Framework. - requestedAssembly.Version <- Version("12.0.0.0") - Assembly.Load (requestedAssembly) - else - null) - AppDomain.CurrentDomain.add_AssemblyResolve(onResolveEvent) -#endif - + let rec pairs l = match l with | [] | [_] -> [] @@ -456,9 +455,6 @@ module internal ProjectCrackerTool = | true, true -> true | _ -> false try -#if !DOTNETCORE - addMSBuildv14BackupResolution () -#endif let props = pairs (List.ofArray argv.[2..]) let opts = getOptions argv.[0] enableLogging props 0, opts @@ -466,8 +462,8 @@ module internal ProjectCrackerTool = 2, { ProjectFile = projectFile; Options = [||]; ReferencedProjectOptions = [||]; - LogOutput = e.ToString() - Error = e.Message } + LogOutput = e.ToString() + " StackTrace: " + e.StackTrace + Error = e.Message + " StackTrace: " + e.StackTrace } else 1, { ProjectFile = ""; Options = [||]; diff --git a/fcs/FSharp.Compiler.Service.ProjectCrackerTool/paket.references b/fcs/FSharp.Compiler.Service.ProjectCrackerTool/paket.references new file mode 100644 index 00000000000..3ad1f9662c7 --- /dev/null +++ b/fcs/FSharp.Compiler.Service.ProjectCrackerTool/paket.references @@ -0,0 +1,4 @@ +Microsoft.Build.Utilities.Core +Microsoft.Build.Engine +Microsoft.Build +System.Threading.Tasks.Dataflow \ No newline at end of file diff --git a/fcs/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj b/fcs/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj index 98e86a06448..d53494b86f2 100644 --- a/fcs/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj +++ b/fcs/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj @@ -80,8 +80,8 @@ PreserveNewest + - @@ -97,7 +97,6 @@ - $(FSharpSourcesRoot)\..\packages\System.Collections.Immutable.$(SystemCollectionsImmutableVersion)\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll @@ -112,7 +111,6 @@ $(FSharpSourcesRoot)\..\packages\FSharp.Compiler.Tools.4.1.27\tools\FSharp.Core.dll true - CSharp_Analysis {887630A3-4B1D-40EA-B8B3-2D842E9C40DB} @@ -130,4 +128,66 @@ + + + + + ..\packages\Microsoft.Build\lib\net45\Microsoft.Build.dll + True + True + + + + + + + + + ..\packages\Microsoft.Build.Engine\lib\net45\Microsoft.Build.Engine.dll + True + True + + + + + + + + + ..\packages\Microsoft.Build.Framework\lib\net45\Microsoft.Build.Framework.dll + True + True + + + + + + + + + ..\packages\Microsoft.Build.Utilities.Core\lib\net45\Microsoft.Build.Utilities.Core.dll + True + True + + + + + + + + + True + + + + + + + + + True + + + + \ No newline at end of file diff --git a/fcs/FSharp.Compiler.Service.Tests/paket.references b/fcs/FSharp.Compiler.Service.Tests/paket.references new file mode 100644 index 00000000000..c64e284f16b --- /dev/null +++ b/fcs/FSharp.Compiler.Service.Tests/paket.references @@ -0,0 +1,3 @@ +Microsoft.Build.Utilities.Core +Microsoft.Build.Engine +Microsoft.Build \ No newline at end of file diff --git a/fcs/build.cmd b/fcs/build.cmd index f7242b03912..c18c0a1f227 100644 --- a/fcs/build.cmd +++ b/fcs/build.cmd @@ -1,11 +1,8 @@ @echo off -dotnet --version -.nuget\NuGet.exe restore -PackagesDirectory packages setlocal cd fcs -dotnet restore tools.fsproj if errorlevel 1 ( endlocal exit /b %errorlevel% diff --git a/fcs/build.fsx b/fcs/build.fsx index d3c850757e4..1e39de8bbb9 100644 --- a/fcs/build.fsx +++ b/fcs/build.fsx @@ -13,8 +13,22 @@ open Fake.ReleaseNotesHelper #if MONO // prevent incorrect output encoding (e.g. https://github.com/fsharp/FAKE/issues/1196) System.Console.OutputEncoding <- System.Text.Encoding.UTF8 + +CleanDir (__SOURCE_DIRECTORY__ + "/../tests/TestResults") +File.WriteAllText(__SOURCE_DIRECTORY__ + "/../tests/TestResults/notestsyet.txt","No tests yet") #endif +let dotnetExePath = DotNetCli.InstallDotNetSDK "2.0.2" + +let runDotnet workingDir args = + let result = + ExecProcess (fun info -> + info.FileName <- dotnetExePath + info.WorkingDirectory <- workingDir + info.Arguments <- args) TimeSpan.MaxValue + + if result <> 0 then failwithf "dotnet %s failed" args + // -------------------------------------------------------------------------------------- // Utilities // -------------------------------------------------------------------------------------- @@ -69,6 +83,22 @@ let buildVersion = else if isAppVeyorBuild then sprintf "%s-b%s" assemblyVersion AppVeyorEnvironment.BuildNumber else assemblyVersion +Target "Clean" (fun _ -> + CleanDir releaseDir +) + +Target "Restore" (fun _ -> + for p in (!! "./../**/packages.config") do + let result = + ExecProcess (fun info -> + info.FileName <- FullName @"./../.nuget/NuGet.exe" + info.WorkingDirectory <- FullName @"./.." + info.Arguments <- sprintf "restore %s -PackagesDirectory \"%s\" -ConfigFile \"%s\"" (FullName p) (FullName "./../packages") (FullName "./../.nuget/NuGet.Config")) TimeSpan.MaxValue + if result <> 0 then failwithf "nuget restore %s failed" p + + runDotnet __SOURCE_DIRECTORY__ "restore tools.fsproj" +) + Target "BuildVersion" (fun _ -> Shell.Exec("appveyor", sprintf "UpdateBuild -Version \"%s\"" buildVersion) |> ignore ) @@ -88,11 +118,24 @@ Target "Build.NetFx" (fun _ -> // Run the unit tests using test runner Target "Test.NetFx" (fun _ -> - !! (releaseDir + "/fcs/net45/FSharp.Compiler.Service.Tests.dll") + let testDir = __SOURCE_DIRECTORY__ + "/../tests/fcs" + CleanDir testDir + + let outDir = releaseDir + "/fcs" + + !! (outDir + "/**/*.*") + |> CopyFiles testDir + + let toolPath = __SOURCE_DIRECTORY__ + "/../packages/NUnit.Console.3.0.0/tools" + !! (toolPath + "/*.*") + |> CopyFiles testDir + + !! (testDir + "/**/FSharp.Compiler.Service.Tests.dll") |> Fake.Testing.NUnit3.NUnit3 (fun p -> { p with - ToolPath = @"..\packages\NUnit.Console.3.0.0\tools\nunit3-console.exe" + ToolPath = testDir + "/nunit3-console.exe" ShadowCopy = false + WorkingDir = FullName testDir TimeOut = TimeSpan.FromMinutes 20. }) ) @@ -109,26 +152,14 @@ Target "NuGet.NetFx" (fun _ -> // -------------------------------------------------------------------------------------- // .NET Core and .NET Core SDK -let isDotnetSDKInstalled = - match Fake.EnvironmentHelper.environVarOrNone "FCS_DNC" with - | Some flag -> - match bool.TryParse flag with - | true, result -> result - | _ -> false - | None -> - try - Shell.Exec("dotnet", "--info") = 0 - with - _ -> false - Target "Build.NetStd" (fun _ -> - runCmdIn __SOURCE_DIRECTORY__ "dotnet" "pack %s -v n -c Release" "FSharp.Compiler.Service.netstandard.sln" + runDotnet __SOURCE_DIRECTORY__ (sprintf "pack %s -v n -c Release" "FSharp.Compiler.Service.netstandard.sln") ) Target "Test.NetStd" (fun _ -> - runCmdIn __SOURCE_DIRECTORY__ "dotnet" "run -p FSharp.Compiler.Service.Tests.netcore/FSharp.Compiler.Service.Tests.netcore.fsproj -c Release -- --result:TestResults.NetStd.xml;format=nunit3" + runDotnet __SOURCE_DIRECTORY__ (sprintf "run -p FSharp.Compiler.Service.Tests.netcore/FSharp.Compiler.Service.Tests.netcore.fsproj -c Release -- --result:TestResults.NetStd.xml;format=nunit3") ) @@ -136,7 +167,7 @@ Target "Test.NetStd" (fun _ -> Target "Nuget.AddNetStd" (fun _ -> let nupkg = sprintf "%s/FSharp.Compiler.Service.%s.nupkg" releaseDir release.AssemblyVersion let netcoreNupkg = sprintf "FSharp.Compiler.Service.netstandard/bin/Release/FSharp.Compiler.Service.%s.nupkg" release.AssemblyVersion - runCmdIn __SOURCE_DIRECTORY__ "dotnet" "mergenupkg --source %s --other %s --framework netstandard1.6" nupkg netcoreNupkg + runDotnet __SOURCE_DIRECTORY__ (sprintf "mergenupkg --source %s --other %s --framework netstandard1.6" nupkg netcoreNupkg) ) @@ -168,7 +199,6 @@ Target "PublishNuGet" (fun _ -> // -------------------------------------------------------------------------------------- // Run all targets by default. Invoke 'build ' to override -Target "Clean" DoNothing Target "Release" DoNothing Target "NuGet" DoNothing Target "Build" DoNothing @@ -177,10 +207,12 @@ Target "TestAndNuGet" DoNothing "Clean" =?> ("BuildVersion", isAppVeyorBuild) + ==> "Restore" ==> "Build.NetStd" "Clean" =?> ("BuildVersion", isAppVeyorBuild) + ==> "Restore" ==> "Build.NetFx" "Build.NetFx" @@ -190,15 +222,15 @@ Target "TestAndNuGet" DoNothing ==> "Test.NetStd" "Build.NetFx" - =?> ("Build.NetStd", isDotnetSDKInstalled) + ==> "Build.NetStd" ==> "Build" "Build.NetStd" - =?> ("Nuget.AddNetStd", isDotnetSDKInstalled) + ==> "Nuget.AddNetStd" "Build.NetFx" ==> "NuGet.NetFx" - =?> ("Nuget.AddNetStd", isDotnetSDKInstalled) + ==> "Nuget.AddNetStd" ==> "NuGet" "Test.NetFx" @@ -206,9 +238,7 @@ Target "TestAndNuGet" DoNothing "NuGet" ==> "TestAndNuGet" - -//"Test.NetStd" -// ==> "TestAndNuGet" + "Build" ==> "NuGet" diff --git a/fcs/build.sh b/fcs/build.sh index d6559cfaa8b..53e6962df76 100755 --- a/fcs/build.sh +++ b/fcs/build.sh @@ -4,10 +4,6 @@ then # use .Net cmd fcs/build.cmd $@ else - dotnet --version - - mono .nuget/NuGet.exe restore -PackagesDirectory packages - cd fcs # use mono @@ -15,8 +11,6 @@ else mozroots --import --sync --quiet fi - dotnet restore tools.fsproj - mono .paket/paket.exe restore exit_code=$? if [ $exit_code -ne 0 ]; then @@ -24,4 +18,4 @@ else fi mono packages/FAKE/tools/FAKE.exe $@ --fsiargs -d:MONO build.fsx -fi \ No newline at end of file +fi diff --git a/fcs/dependencies/MSBuild.v14.0/Microsoft.Build.Engine.dll b/fcs/dependencies/MSBuild.v14.0/Microsoft.Build.Engine.dll deleted file mode 100644 index 06611509976..00000000000 Binary files a/fcs/dependencies/MSBuild.v14.0/Microsoft.Build.Engine.dll and /dev/null differ diff --git a/fcs/dependencies/MSBuild.v14.0/Microsoft.Build.Framework.dll b/fcs/dependencies/MSBuild.v14.0/Microsoft.Build.Framework.dll deleted file mode 100644 index 74d6e05b852..00000000000 Binary files a/fcs/dependencies/MSBuild.v14.0/Microsoft.Build.Framework.dll and /dev/null differ diff --git a/fcs/dependencies/MSBuild.v14.0/Microsoft.Build.dll b/fcs/dependencies/MSBuild.v14.0/Microsoft.Build.dll deleted file mode 100644 index c702184ec02..00000000000 Binary files a/fcs/dependencies/MSBuild.v14.0/Microsoft.Build.dll and /dev/null differ diff --git a/fcs/dependencies/README.md b/fcs/dependencies/README.md deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/fcs/paket.dependencies b/fcs/paket.dependencies index bfd298568f6..39535eedd9d 100644 --- a/fcs/paket.dependencies +++ b/fcs/paket.dependencies @@ -1,7 +1,12 @@ -framework: net45 +framework: net45, net46 source https://www.nuget.org/api/v2/ nuget FAKE nuget FSharp.Formatting +nuget Microsoft.Build.Utilities.Core 14.3.0 +nuget Microsoft.Build.Framework 14.3.0 +nuget Microsoft.Build.Engine 14.3.0 +nuget Microsoft.Build 14.3.0 +nuget System.Threading.Tasks.Dataflow 4.5.24.0 \ No newline at end of file diff --git a/fcs/paket.lock b/fcs/paket.lock index 2e454bee770..947bfc412b7 100644 --- a/fcs/paket.lock +++ b/fcs/paket.lock @@ -1,4 +1,4 @@ -RESTRICTION: == net45 +RESTRICTION: || (== net45) (== net46) NUGET remote: https://www.nuget.org/api/v2 FAKE (4.63.2) @@ -8,3 +8,17 @@ NUGET FSharpVSPowerTools.Core (>= 2.3 < 2.4) FSharpVSPowerTools.Core (2.3) FSharp.Compiler.Service (>= 2.0.0.3) + Microsoft.Build (14.3) + Microsoft.Build.Framework (14.3) + Microsoft.Build.Engine (14.3) + Microsoft.Build.Framework (14.3) + Microsoft.Build.Framework (14.3) + System.Collections (>= 4.0.11) - restriction: || (&& (== net45) (>= netstandard1.3)) (== net46) + System.Runtime (>= 4.1) - restriction: || (&& (== net45) (>= netstandard1.3)) (== net46) + System.Runtime.InteropServices (>= 4.1) - restriction: || (&& (== net45) (>= netstandard1.3)) (== net46) + Microsoft.Build.Utilities.Core (14.3) + Microsoft.Build.Framework (14.3) + System.Collections (4.3) - restriction: || (&& (== net45) (>= netstandard1.3)) (== net46) + System.Runtime (4.3) - restriction: || (&& (== net45) (>= netstandard1.3)) (== net46) + System.Runtime.InteropServices (4.3) - restriction: || (&& (== net45) (>= netstandard1.3)) (== net46) + System.Threading.Tasks.Dataflow (4.5.24) diff --git a/netci.groovy b/netci.groovy index 185ea17a197..ddf51e05e7d 100644 --- a/netci.groovy +++ b/netci.groovy @@ -105,7 +105,7 @@ ${buildPath}build.cmd ${buildFlavor} ${build_args}""") Utilities.addArchival(newJob, "tests/TestResults/*.*", "", skipIfNoTestFiles, false) if (configuration == "Release_fcs") { - Utilities.addArchival(newJob, "Release/fcs/**") + Utilities.addArchival(newJob, "Release/**") } else { Utilities.addArchival(newJob, "${buildFlavor}/**") diff --git a/tests/service/ProjectOptionsTests.fs b/tests/service/ProjectOptionsTests.fs index 4fddf734b6a..39ecd5124b4 100644 --- a/tests/service/ProjectOptionsTests.fs +++ b/tests/service/ProjectOptionsTests.fs @@ -20,6 +20,10 @@ open FSharp.Compiler.Service.Tests.Common #if !NO_PROJECTCRACKER +let hasMSBuild14 = + use engine = new Microsoft.Build.Evaluation.ProjectCollection() + engine.Toolsets |> Seq.exists (fun x -> x.ToolsPath.Contains "v14.0") + let normalizePath s = (new Uri(s)).LocalPath let checkOption (opts:string[]) s = @@ -90,7 +94,7 @@ let ``Project file parsing example 1 Default configuration relative path`` () = [] let ``Project file parsing VS2013_FSharp_Portable_Library_net45``() = - if not runningOnMono then // Disabled on Mono due to lack of installed PCL reference libraries - the modern way is to reference the FSHarp.Core nuget package so this is ok + if (not hasMSBuild14) || runningOnMono then () else // Disabled on Mono due to lack of installed PCL reference libraries - the modern way is to reference the FSHarp.Core nuget package so this is ok let projectFile = __SOURCE_DIRECTORY__ + @"/../projects/Sample_VS2013_FSharp_Portable_Library_net45/Sample_VS2013_FSharp_Portable_Library_net45.fsproj" let options = ProjectCracker.GetProjectOptionsFromProjectFile(projectFile, []) @@ -106,7 +110,7 @@ let ``Project file parsing VS2013_FSharp_Portable_Library_net45``() = [] let ``Project file parsing Sample_VS2013_FSharp_Portable_Library_net451_adjusted_to_profile78``() = - if not runningOnMono then // Disabled on Mono due to lack of installed PCL reference libraries - the modern way is to reference the FSHarp.Core nuget package so this is ok + if (not hasMSBuild14) || runningOnMono then () else // Disabled on Mono due to lack of installed PCL reference libraries - the modern way is to reference the FSHarp.Core nuget package so this is ok let projectFile = __SOURCE_DIRECTORY__ + @"/../projects/Sample_VS2013_FSharp_Portable_Library_net451_adjusted_to_profile78/Sample_VS2013_FSharp_Portable_Library_net451.fsproj" Directory.SetCurrentDirectory(__SOURCE_DIRECTORY__ + @"/../projects/Sample_VS2013_FSharp_Portable_Library_net451_adjusted_to_profile78/") @@ -141,7 +145,8 @@ let ``Project file parsing -- bad project file``() = ProjectCracker.GetProjectOptionsFromProjectFileLogged(f) |> ignore failwith "Expected exception" with e -> - Assert.That(e.Message, Contains.Substring "The project file could not be loaded.") + Assert.That(e.Message, Contains.Substring "Could not load project") + Assert.That(e.Message, Contains.Substring "Malformed.fsproj") [] let ``Project file parsing -- non-existent project file``() = @@ -149,7 +154,7 @@ let ``Project file parsing -- non-existent project file``() = try ProjectCracker.GetProjectOptionsFromProjectFileLogged(f, enableLogging=true) |> ignore with e -> - Assert.That(e.Message, Contains.Substring "Could not find file") + Assert.That(e.Message, Contains.Substring "DoesNotExist.fsproj") [] let ``Project file parsing -- output file``() = @@ -175,9 +180,20 @@ let ``Project file parsing -- references``() = references |> should haveLength 4 p.ReferencedProjects |> should be Empty +[] +let ``Project file parsing -- no project references``() = + let p = ProjectCracker.GetProjectOptionsFromProjectFile(__SOURCE_DIRECTORY__ + @"/data/Test3.fsproj") + + let references = getReferencedFilenames p.OtherOptions + checkOption references "FSharp.Core.dll" + checkOption references "mscorlib.dll" + checkOption references "System.Core.dll" + checkOption references "System.dll" + p.ReferencedProjects |> should haveLength 0 + [] let ``Project file parsing -- 2nd level references``() = - let p = ProjectCracker.GetProjectOptionsFromProjectFile(__SOURCE_DIRECTORY__ + @"/data/Test2.fsproj") + let p,_ = ProjectCracker.GetProjectOptionsFromProjectFileLogged(__SOURCE_DIRECTORY__ + @"/data/Test2.fsproj", enableLogging=true) let references = getReferencedFilenames p.OtherOptions checkOption references "FSharp.Core.dll" @@ -190,6 +206,7 @@ let ``Project file parsing -- 2nd level references``() = p.ReferencedProjects |> should haveLength 1 (snd p.ReferencedProjects.[0]).ProjectFileName |> should contain (normalizePath (__SOURCE_DIRECTORY__ + @"/data/Test1.fsproj")) + [] let ``Project file parsing -- reference project output file``() = let p = ProjectCracker.GetProjectOptionsFromProjectFile(__SOURCE_DIRECTORY__ + @"/data/DifferingOutputDir/Dir2/Test2.fsproj") @@ -207,20 +224,23 @@ let ``Project file parsing -- reference project output file``() = [] let ``Project file parsing -- Tools Version 12``() = + if not hasMSBuild14 then () else let opts = ProjectCracker.GetProjectOptionsFromProjectFile(__SOURCE_DIRECTORY__ + @"/data/ToolsVersion12.fsproj") checkOption (getReferencedFilenames opts.OtherOptions) "System.Core.dll" [] let ``Project file parsing -- Logging``() = + if not hasMSBuild14 then () else let projectFileName = normalizePath (__SOURCE_DIRECTORY__ + @"/data/ToolsVersion12.fsproj") let _, logMap = ProjectCracker.GetProjectOptionsFromProjectFileLogged(projectFileName, enableLogging=true) let log = logMap.[projectFileName] - + + Assert.That(log, Is.StringContaining("ResolveAssemblyReference")) if runningOnMono then - Assert.That(log, Is.StringContaining("Reference System.Core resolved")) - Assert.That(log, Is.StringContaining("Using task ResolveAssemblyReference from Microsoft.Build.Tasks.ResolveAssemblyReference")) - else - Assert.That(log, Is.StringContaining("""Using "ResolveAssemblyReference" task from assembly "Microsoft.Build.Tasks.Core, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a".""")) + Assert.That(log, Is.StringContaining("System.Core")) + Assert.That(log, Is.StringContaining("Microsoft.Build.Tasks.ResolveAssemblyReference")) + else + Assert.That(log, Is.StringContaining("Microsoft.Build.Tasks.Core")) [] let ``Project file parsing -- FSharpProjectOptions.SourceFiles contains both fs and fsi files``() = @@ -237,6 +257,7 @@ let ``Project file parsing -- FSharpProjectOptions.SourceFiles contains both fs [] let ``Project file parsing -- Full path``() = + if not hasMSBuild14 then () else let f = normalizePath (__SOURCE_DIRECTORY__ + @"/data/ToolsVersion12.fsproj") let p = ProjectCracker.GetProjectOptionsFromProjectFile(f) p.ProjectFileName |> should equal f @@ -253,6 +274,7 @@ let ``Project file parsing -- project references``() = [] let ``Project file parsing -- multi language project``() = + if not hasMSBuild14 then () else let f = normalizePath (__SOURCE_DIRECTORY__ + @"/data/MultiLanguageProject/ConsoleApplication1.fsproj") let options = ProjectCracker.GetProjectOptionsFromProjectFile(f) @@ -265,8 +287,7 @@ let ``Project file parsing -- multi language project``() = [] let ``Project file parsing -- PCL profile7 project``() = - if not runningOnMono then // Disabled on Mono due to lack of installed PCL reference libraries - the modern way is to reference the FSHarp.Core nuget package so this is ok - + if (not hasMSBuild14) || runningOnMono then () else // Disabled on Mono due to lack of installed PCL reference libraries - the modern way is to reference the FSHarp.Core nuget package so this is ok let f = normalizePath (__SOURCE_DIRECTORY__ + @"/../projects/Sample_VS2013_FSharp_Portable_Library_net45/Sample_VS2013_FSharp_Portable_Library_net45.fsproj") @@ -315,8 +336,7 @@ let ``Project file parsing -- PCL profile7 project``() = [] let ``Project file parsing -- PCL profile78 project``() = - if not runningOnMono then // Disabled on Mono due to lack of installed PCL reference libraries - the modern way is to reference the FSHarp.Core nuget package so this is ok - + if (not hasMSBuild14) || runningOnMono then () else // Disabled on Mono due to lack of installed PCL reference libraries - the modern way is to reference the FSHarp.Core nuget package so this is ok let f = normalizePath (__SOURCE_DIRECTORY__ + @"/../projects/Sample_VS2013_FSharp_Portable_Library_net451_adjusted_to_profile78/Sample_VS2013_FSharp_Portable_Library_net451.fsproj") @@ -356,7 +376,7 @@ let ``Project file parsing -- PCL profile78 project``() = [] let ``Project file parsing -- PCL profile259 project``() = - if not runningOnMono then // Disabled on Mono due to lack of installed PCL reference libraries - the modern way is to reference the FSHarp.Core nuget package so this is ok + if (not hasMSBuild14) || runningOnMono then () else // Disabled on Mono due to lack of installed PCL reference libraries - the modern way is to reference the FSHarp.Core nuget package so this is ok let f = normalizePath (__SOURCE_DIRECTORY__ + @"/../projects/Sample_VS2013_FSharp_Portable_Library_net451_adjusted_to_profile259/Sample_VS2013_FSharp_Portable_Library_net451.fsproj") let options = ProjectCracker.GetProjectOptionsFromProjectFile(f) @@ -468,9 +488,11 @@ let ``Test OtherOptions order for GetProjectOptionsFromScript`` () = projOpts.OtherOptions |> Array.map (fun s -> if s.StartsWith "--" then s else Path.GetFileNameWithoutExtension s) - |> Array.sort - |> shouldEqual (Array.sort expected2) - let otherArgs = [|"--noframework"; "--warn:3"; "System.Numerics"; "mscorlib"; "FSharp.Core"; "System"; "System.Xml"; "System.Runtime.Remoting"; "System.Runtime.Serialization.Formatters.Soap"; "System.Data"; "System.Drawing"; "System.Core"; "System.Runtime"; "System.Linq"; "System.Reflection"; "System.Linq.Expressions"; "System.Threading.Tasks"; "System.IO"; "System.Net.Requests"; "System.Collections"; "System.Runtime.Numerics"; "System.Threading"; "System.Web"; "System.Web.Services"; "System.Windows.Forms"; "FSharp.Compiler.Interactive.Settings"|] + |> Array.forall (fun s -> Set.contains s expected2) + |> shouldEqual true + + let otherArgs = [|"--noframework"; "--warn:3"; "System.Numerics"; "mscorlib"; "FSharp.Core"; "System"; "System.Xml"; "System.Runtime.Remoting"; "System.Runtime.Serialization.Formatters.Soap"; "System.Data"; "System.Drawing"; "System.Core"; "System.Runtime"; "System.Linq"; "System.Reflection"; "System.Linq.Expressions"; "System.Threading.Tasks"; "System.IO"; "System.Net.Requests"; "System.Collections"; "System.Runtime.Numerics"; "System.Threading"; "System.Web"; "System.Web.Services"; "System.Windows.Forms"; "FSharp.Compiler.Interactive.Settings"|] |> Set.ofArray + test "Main1" otherArgs test "Main2" otherArgs test "Main3" otherArgs diff --git a/tests/service/data/Test3.fsproj b/tests/service/data/Test3.fsproj new file mode 100644 index 00000000000..31c2d33c565 --- /dev/null +++ b/tests/service/data/Test3.fsproj @@ -0,0 +1,62 @@ + + + + Debug + x86 + 8.0.30703 + 2.0 + {116cc2f9-f987-4b3d-915a-34cac04a73db} + ..\..\..\$(Configuration)\net40\bin + Exe + Test2 + Test2 + Test2 + False + 11 + + + True + full + False + False + DEBUG;TRACE + 3 + x86 + bin\Debug\Test2.xml + + + pdbonly + True + True + TRACE + 3 + x86 + bin\Release\Test2.xml + False + + + + ..\..\..\packages\Microsoft.Portable.FSharp.Core.4.1.20\lib\profiles\net40\FSharp.Core.dll + false + + + + + + + + + + + + + + + ..\..\..\packages\NUnit\lib\nunit.framework.dll + True + True + + + + + \ No newline at end of file