diff --git a/build.template b/build.template index b6efcd4..01b4c2a 100644 --- a/build.template +++ b/build.template @@ -1,13 +1,16 @@ -// -------------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------------- // FAKE build script // -------------------------------------------------------------------------------------- #r @"packages/FAKE/tools/FakeLib.dll" - +#r @"packages/Paket.Core/lib/Paket.Core.dll" open Fake open Fake.Git open Fake.AssemblyInfoFile open Fake.ReleaseNotesHelper +open Paket +open Paket.PackageResolver +open Paket.Requirements open System open System.IO #if MONO @@ -98,6 +101,16 @@ Target "AssemblyInfo" (fun _ -> csProjs |> Seq.iter genCSAssemblyInfo ) +// Copies binaries from default VS location to exepcted bin folder +// But keeps a subdirectory structure for each project in the +// src folder to support multiple project outputs +Target "CopyBinaries" (fun _ -> + directoryInfo "src" + |> subDirectories + |> Array.map (fun d -> (d.Name, sprintf "%s/Bin/Release" d.FullName)) + |> Array.iter (fun (n, p) -> CopyDir (sprintf "bin/%s" n) p (fun _ -> true)) +) + // -------------------------------------------------------------------------------------- // Clean build results @@ -155,21 +168,126 @@ Target "SourceLink" (fun _ -> // -------------------------------------------------------------------------------------- // Build a NuGet package +type FrameworkVersion (projectFwVersion:string) = + let nugetFwVersion = projectFwVersion.Replace("v","net") + member x.NugetFwVersion = nugetFwVersion + +type Output = +| Exe +| Library + +let dirI = + directoryInfo ((__SOURCE_DIRECTORY__ @@ "bin") @@ "Tu.Tu") + +let getProjectFile (d:IO.DirectoryInfo) = + let dirI = directoryInfo ((__SOURCE_DIRECTORY__ @@ "src") @@ d.Name) + if not dirI.Exists then failwith (sprintf "%s does not exist" dirI.FullName ) + let pfile = match dirI.GetFiles("*.?sproj") with + | [|unique|] -> ProjectFile.Load unique.FullName + | [||] -> failwith (sprintf "No project files found in %s" d.FullName) + | many -> failwith (sprintf "More than one project file was found in %s: %A" d.FullName many) + + match pfile with + | Some(p) -> p + | None -> failwith "Unable to load project file" + +let getNodes (p:ProjectFile) name = + let query = (sprintf "//ns:%s" name) + let nodes = p.Document.SelectNodes((sprintf "//ns:%s" name), p.Namespaces) + match nodes.Count with + | 0 -> None + | _ -> Some(nodes) + +let getNode (p:ProjectFile) name = + match getNodes p name with + | None -> failwith (sprintf "%s Not found in project file %s" name p.FileName) + | Some(n) when n.Count > 1 -> failwith (sprintf "More than one element of %s found in project file %s" name p.FileName) + | Some(n) -> n.[0] + +let getOutputType (d:IO.DirectoryInfo) = + let projFile = getProjectFile d + let output = (getNode projFile "OutputType").InnerText + let fw = (getNode projFile "TargetFrameworkVersion").InnerText + match output with + | "Exe" -> (Exe, (new FrameworkVersion(fw))) + | _ -> (Library, (new FrameworkVersion(fw))) + +let getFilenamesForLibraryOutput (d:IO.DirectoryInfo) = + [d.FullName @@ (sprintf "%s.dll" d.Name) + d.FullName @@ (sprintf "%s.pdb" d.Name)] + +let getFilenamesForExeOutput (d:IO.DirectoryInfo) = + d.GetFiles("*", IO.SearchOption.AllDirectories) + |> Array.map (fun f -> f.FullName) + |> Array.toList + +let getFilenames (d:IO.DirectoryInfo) = + let (output, fwVersion) = getOutputType d + let files = match output with + | Exe -> getFilenamesForExeOutput d + | Library -> getFilenamesForLibraryOutput d + files |> List.map(fun f -> (f, Some("lib" @@ fwVersion.NugetFwVersion), None)) + +let getAllPackages () = + let dep = (DependenciesFile.ReadFromFile (__SOURCE_DIRECTORY__ @@ "paket.dependencies")) + let lock = (LockFileParser.Parse (IO.File.ReadAllLines (__SOURCE_DIRECTORY__ @@ "paket.lock"))) + (dep.Packages, lock.Packages) + +let getReferencedPackageNamesFromProject projectRefFile = + IO.File.ReadAllLines projectRefFile + +let getCurrentlyInstalledVersion p (resolved:ResolvedPackage List) = + (resolved |> List.find (fun rp -> rp.Name = p)).Version + +let getVersionRequirement (p:PackageRequirement) (resolved:ResolvedPackage List) = + match p.VersionRequirement.Range with + | Minimum(semver) when (semver.ToString()) = "0" -> Minimum(getCurrentlyInstalledVersion p.Name resolved) + | version -> version + +let getReferencedPackagesFromProject projectRefFile = + let referencedPackages = getReferencedPackageNamesFromProject projectRefFile + let (dep, lock) = getAllPackages () + dep + |> List.filter (fun p -> referencedPackages |> Array.exists (fun r -> p.Name = r)) + |> List.map (fun p -> let version = getVersionRequirement p lock |> NugetVersionRangeParser.format + (p.Name, version)) + +let getInterProjectDependencies (d:IO.DirectoryInfo) = + let projFile = getProjectFile d + match getNodes projFile "ProjectReference" with + | None -> [] + | Some(nodes) -> [for n in nodes -> (n.SelectSingleNode("ns:Name", projFile.Namespaces).InnerText, release.NugetVersion)] + +let getDependencies (d:IO.DirectoryInfo) = + match getOutputType d with + | Exe,_ -> [] + | _ ,_ -> let projectSourceDir = (__SOURCE_DIRECTORY__ @@ "src") @@ d.Name + let referencesFile = projectSourceDir @@ "paket.references" + let externalDependencies = match fileExists referencesFile with + | false -> [] + | true -> getReferencedPackagesFromProject referencesFile + (getInterProjectDependencies d) @ externalDependencies + Target "NuGet" (fun _ -> - NuGet (fun p -> - { p with - Authors = authors - Project = project - Summary = summary - Description = description - Version = release.NugetVersion - ReleaseNotes = String.Join(Environment.NewLine, release.Notes) - Tags = tags - OutputPath = "bin" - AccessKey = getBuildParamOrDefault "nugetkey" "" - Publish = hasBuildParam "nugetkey" - Dependencies = [] }) - ("nuget/" + project + ".nuspec") + directoryInfo "bin" + |> subDirectories + |> Array.iter (fun d -> + NuGet (fun p -> + { p with + Authors = authors + Project = d.Name + Summary = summary + Description = description + Version = release.NugetVersion + ReleaseNotes = String.Join(Environment.NewLine, release.Notes) + Tags = tags + Files = getFilenames d + OutputPath = "bin" @@ d.Name + AccessKey = getBuildParamOrDefault "nugetkey" "" + Publish = hasBuildParam "nugetkey" + Dependencies = getDependencies d }) + ("nuget/" + project + ".nuspec") + ) ) // -------------------------------------------------------------------------------------- @@ -265,6 +383,7 @@ Target "All" DoNothing "Clean" ==> "AssemblyInfo" ==> "Build" + ==> "CopyBinaries" ==> "RunTests" =?> ("GenerateReferenceDocs",isLocalBuild && not isMono) =?> ("GenerateDocs",isLocalBuild && not isMono) diff --git a/docs/tools/generate.template b/docs/tools/generate.template index ac943e4..73185e2 100644 --- a/docs/tools/generate.template +++ b/docs/tools/generate.template @@ -3,8 +3,6 @@ // (the generated documentation is stored in the 'docs/output' directory) // -------------------------------------------------------------------------------------- -// Binaries that have XML documentation (in a corresponding generated XML file) -let referenceBinaries = [ "##ProjectName##.dll" ] // Web site location for the generated documentation let website = "/##ProjectName##" @@ -67,18 +65,28 @@ let copyFiles () = CopyRecursive (formatting @@ "styles") (output @@ "content") true |> Log "Copying styles and scripts: " +let findBinaries () = + directoryInfo bin + |> subDirectories + |> Array.map (fun d -> d.FullName @@ (sprintf "%s.dll" d.Name)) + |> List.ofArray + +let findLibDirs () = + directoryInfo bin + |> subDirectories + |> Array.map (fun d -> d.FullName) + |> List.ofArray + // Build API reference from XML comments let buildReference () = CleanDir (output @@ "reference") - let binaries = - referenceBinaries - |> List.map (fun lib-> bin @@ lib) + let binaries = findBinaries () MetadataFormat.Generate ( binaries, output @@ "reference", layoutRoots, parameters = ("root", root)::info, sourceRepo = githubLink @@ "tree/master", sourceFolder = __SOURCE_DIRECTORY__ @@ ".." @@ "..", - publicOnly = true, libDirs = [bin] ) + publicOnly = true,libDirs = (findLibDirs ()) ) // Build documentation from `fsx` and `md` files in `docs/content` let buildDocumentation () = diff --git a/nuget/FSharp.ProjectTemplate.nuspec b/nuget/FSharp.ProjectTemplate.nuspec index ebd2d3a..08a9d80 100644 --- a/nuget/FSharp.ProjectTemplate.nuspec +++ b/nuget/FSharp.ProjectTemplate.nuspec @@ -14,10 +14,7 @@ @releaseNotes@ Copyright 2013 @tags@ - + @dependencies@ - - - - + @files@ diff --git a/paket.dependencies b/paket.dependencies index fa7072a..5830d85 100644 --- a/paket.dependencies +++ b/paket.dependencies @@ -6,5 +6,6 @@ nuget NUnit.Runners nuget Nuget.CommandLine nuget FAKE nuget SourceLink.Fake +nuget Paket.Core -github fsharp/FAKE modules/Octokit/Octokit.fsx \ No newline at end of file +github fsharp/FAKE modules/Octokit/Octokit.fsx diff --git a/src/FSharp.ProjectTemplate/FSharp.ProjectTemplate.fsproj b/src/FSharp.ProjectTemplate/FSharp.ProjectTemplate.fsproj index 8eb45da..f0aae4c 100644 --- a/src/FSharp.ProjectTemplate/FSharp.ProjectTemplate.fsproj +++ b/src/FSharp.ProjectTemplate/FSharp.ProjectTemplate.fsproj @@ -19,19 +19,19 @@ full false false - ..\..\bin + .\bin\Debug DEBUG;TRACE 3 - ..\..\bin\FSharp.ProjectTemplate.xml + .\bin\Debug\FSharp.ProjectTemplate.xml pdbonly true true - ..\..\bin + .\bin\Release TRACE 3 - ..\..\bin\FSharp.ProjectTemplate.xml + .\bin\Release\FSharp.ProjectTemplate.xml @@ -70,4 +70,4 @@ --> - \ No newline at end of file +