forked from tsai/mathnet-numerics
3 changed files with 409 additions and 345 deletions
@ -0,0 +1,342 @@ |
|||||
|
// __ __ _ _ _ _ ______ _______ |
||||
|
// | \/ | | | | | | \ | | ____|__ __| |
||||
|
// | \ / | __ _| |_| |__ | \| | |__ | | |
||||
|
// | |\/| |/ _` | __| '_ \ | . ` | __| | | |
||||
|
// | | | | (_| | |_| | | |_| |\ | |____ | | |
||||
|
// |_| |_|\__,_|\__|_| |_(_)_| \_|______| |_| |
||||
|
// |
||||
|
// Math.NET Numerics - https://numerics.mathdotnet.com |
||||
|
// Copyright (c) Math.NET - Open Source MIT/X11 License |
||||
|
// |
||||
|
// Build Framework using FAKE (http://fsharp.github.io/FAKE) |
||||
|
// |
||||
|
|
||||
|
module BuildFramework |
||||
|
|
||||
|
#I "../packages/build/FAKE/tools" |
||||
|
#r "../packages/build/FAKE/tools/FakeLib.dll" |
||||
|
|
||||
|
open Fake |
||||
|
open Fake.DocuHelper |
||||
|
open Fake.AssemblyInfoFile |
||||
|
open Fake.ReleaseNotesHelper |
||||
|
open Fake.StringHelper |
||||
|
open Fake.Testing.NUnit3 |
||||
|
open System |
||||
|
open System.IO |
||||
|
|
||||
|
Environment.CurrentDirectory <- Path.Combine (__SOURCE_DIRECTORY__ + "/../") |
||||
|
trace Environment.CurrentDirectory |
||||
|
|
||||
|
let header = ReadFile(__SOURCE_DIRECTORY__ </> __SOURCE_FILE__) |> Seq.take 10 |> Seq.map (fun s -> s.Substring(2)) |> toLines |
||||
|
trace header |
||||
|
|
||||
|
type BundleRelease = |
||||
|
{ ReleaseNotesFile: string |
||||
|
AssemblyVersion: string |
||||
|
PackageVersion: string |
||||
|
ReleaseNotes: string } |
||||
|
|
||||
|
type Package = |
||||
|
{ Id: string |
||||
|
Version: string |
||||
|
Title: string |
||||
|
Summary: string |
||||
|
Description: string |
||||
|
ReleaseNotes: string |
||||
|
Tags: string |
||||
|
FsLoader: bool |
||||
|
Authors: string list |
||||
|
Dependencies: NugetFrameworkDependencies list |
||||
|
Files: (string * string option * string option) list } |
||||
|
|
||||
|
type Bundle = |
||||
|
{ Id: string |
||||
|
Version: string |
||||
|
Title: string |
||||
|
ReleaseNotesFile: string |
||||
|
Packages: Package list } |
||||
|
|
||||
|
let release releaseNotesFile : BundleRelease = |
||||
|
let info = LoadReleaseNotes releaseNotesFile |
||||
|
let buildPart = "0" |
||||
|
let assemblyVersion = info.AssemblyVersion + "." + buildPart |
||||
|
let packageVersion = info.NugetVersion |
||||
|
let notes = info.Notes |> List.map (fun l -> l.Replace("*","").Replace("`","")) |> toLines |
||||
|
{ ReleaseNotesFile = releaseNotesFile |
||||
|
AssemblyVersion = assemblyVersion |
||||
|
PackageVersion = packageVersion |
||||
|
ReleaseNotes = notes } |
||||
|
|
||||
|
|
||||
|
// -------------------------------------------------------------------------------------- |
||||
|
// TARGET FRAMEWORKS |
||||
|
// -------------------------------------------------------------------------------------- |
||||
|
|
||||
|
let libnet35 = "lib/net35" |
||||
|
let libnet40 = "lib/net40" |
||||
|
let libnet45 = "lib/net45" |
||||
|
let libpcl7 = "lib/portable-net45+netcore45+MonoAndroid1+MonoTouch1" |
||||
|
let libpcl47 = "lib/portable-net45+sl5+netcore45+MonoAndroid1+MonoTouch1" |
||||
|
let libpcl78 = "lib/portable-net45+netcore45+wp8+MonoAndroid1+MonoTouch1" |
||||
|
let libpcl259 = "lib/portable-net45+netcore45+wpa81+wp8+MonoAndroid1+MonoTouch1" |
||||
|
let libpcl328 = "lib/portable-net4+sl5+netcore45+wpa81+wp8+MonoAndroid1+MonoTouch1" |
||||
|
|
||||
|
|
||||
|
// -------------------------------------------------------------------------------------- |
||||
|
// PREPARE |
||||
|
// -------------------------------------------------------------------------------------- |
||||
|
|
||||
|
let patchVersionInAssemblyInfo path (release:BundleRelease) = |
||||
|
BulkReplaceAssemblyInfoVersions path (fun f -> |
||||
|
{ f with |
||||
|
AssemblyVersion = release.AssemblyVersion |
||||
|
AssemblyFileVersion = release.AssemblyVersion |
||||
|
AssemblyInformationalVersion = release.PackageVersion }) |
||||
|
|
||||
|
let patchVersionInResource path (release:BundleRelease) = |
||||
|
ReplaceInFile |
||||
|
(regex_replace @"\d+\.\d+\.\d+\.\d+" release.AssemblyVersion |
||||
|
>> regex_replace @"\d+,\d+,\d+,\d+" (replace "." "," release.AssemblyVersion)) |
||||
|
path |
||||
|
|
||||
|
|
||||
|
// -------------------------------------------------------------------------------------- |
||||
|
// BUILD |
||||
|
// -------------------------------------------------------------------------------------- |
||||
|
|
||||
|
let buildConfig config subject = MSBuild "" (if hasBuildParam "incremental" then "Build" else "Rebuild") [ "Configuration", config ] subject |> ignore |
||||
|
let build subject = buildConfig "Release" subject |
||||
|
let buildSigned subject = buildConfig "Release-Signed" subject |
||||
|
let buildConfig32 config subject = MSBuild "" (if hasBuildParam "incremental" then "Build" else "Rebuild") [("Configuration", config); ("Platform","Win32")] subject |> ignore |
||||
|
let buildConfig64 config subject = MSBuild "" (if hasBuildParam "incremental" then "Build" else "Rebuild") [("Configuration", config); ("Platform","x64")] subject |> ignore |
||||
|
|
||||
|
|
||||
|
// -------------------------------------------------------------------------------------- |
||||
|
// TEST |
||||
|
// -------------------------------------------------------------------------------------- |
||||
|
|
||||
|
let test target = |
||||
|
let quick p = if hasBuildParam "quick" then { p with Where="cat!=LongRunning" } else p |
||||
|
NUnit3 (fun p -> |
||||
|
{ p with |
||||
|
ShadowCopy = false |
||||
|
Labels = LabelsLevel.Off |
||||
|
TimeOut = TimeSpan.FromMinutes 60. } |> quick) target |
||||
|
|
||||
|
let test32 target = |
||||
|
let quick p = if hasBuildParam "quick" then { p with Where="cat!=LongRunning" } else p |
||||
|
NUnit3 (fun p -> |
||||
|
{ p with |
||||
|
Force32bit = true |
||||
|
ShadowCopy = false |
||||
|
Labels = LabelsLevel.Off |
||||
|
TimeOut = TimeSpan.FromMinutes 60. } |> quick) target |
||||
|
|
||||
|
|
||||
|
// -------------------------------------------------------------------------------------- |
||||
|
// PACKAGES |
||||
|
// -------------------------------------------------------------------------------------- |
||||
|
|
||||
|
let provideLicense path = |
||||
|
ReadFileAsString "LICENSE.md" |
||||
|
|> ConvertTextToWindowsLineBreaks |
||||
|
|> ReplaceFile (path </> "license.txt") |
||||
|
|
||||
|
let provideReadme title releasenotes path = |
||||
|
String.concat Environment.NewLine [header; " " + title; ""; ReadFileAsString releasenotes] |
||||
|
|> ConvertTextToWindowsLineBreaks |
||||
|
|> ReplaceFile (path </> "readme.txt") |
||||
|
|
||||
|
let provideFsLoader includes path = |
||||
|
// inspired by FsLab/tpetricek |
||||
|
let fullScript = ReadFile "src/FSharp/MathNet.Numerics.fsx" |> Array.ofSeq |
||||
|
let startIndex = fullScript |> Seq.findIndex (fun s -> s.Contains "***MathNet.Numerics.fsx***") |
||||
|
let extraScript = fullScript .[startIndex + 1 ..] |> List.ofSeq |
||||
|
let assemblies = [ "MathNet.Numerics.dll"; "MathNet.Numerics.FSharp.dll" ] |
||||
|
let nowarn = ["#nowarn \"211\""] |
||||
|
let references = [ for assembly in assemblies -> sprintf "#r \"%s\"" assembly ] |
||||
|
ReplaceFile (path </> "MathNet.Numerics.fsx") (nowarn @ includes @ references @ extraScript |> toLines) |
||||
|
|
||||
|
let provideFsIfSharpLoader path = |
||||
|
let fullScript = ReadFile "src/FSharp/MathNet.Numerics.IfSharp.fsx" |> Array.ofSeq |
||||
|
let startIndex = fullScript |> Seq.findIndex (fun s -> s.Contains "***MathNet.Numerics.IfSharp.fsx***") |
||||
|
ReplaceFile (path </> "MathNet.Numerics.IfSharp.fsx") (fullScript .[startIndex + 1 ..] |> toLines) |
||||
|
|
||||
|
let provideZipExtraFiles path (bundle:Bundle) = |
||||
|
provideLicense path |
||||
|
provideReadme (sprintf "%s v%s" bundle.Title bundle.Version) bundle.ReleaseNotesFile path |
||||
|
if bundle.Packages |> List.exists (fun p -> p.FsLoader) then |
||||
|
let includes = [ for root in [ ""; "../"; "../../" ] -> sprintf "#I \"%sNet40\"" root ] |
||||
|
provideFsLoader includes path |
||||
|
provideFsIfSharpLoader path |
||||
|
|
||||
|
let provideNuGetExtraFiles path (bundle:Bundle) (pack:Package) = |
||||
|
provideLicense path |
||||
|
provideReadme (sprintf "%s v%s" pack.Title pack.Version) bundle.ReleaseNotesFile path |
||||
|
if pack.FsLoader then |
||||
|
let includes = [ for root in [ ""; "../"; "../../"; "../../../" ] do |
||||
|
for package in bundle.Packages do |
||||
|
yield sprintf "#I \"%spackages/%s/lib/net40/\"" root package.Id |
||||
|
yield sprintf "#I \"%spackages/%s.%s/lib/net40/\"" root package.Id package.Version ] |
||||
|
provideFsLoader includes path |
||||
|
provideFsIfSharpLoader path |
||||
|
|
||||
|
// ZIP |
||||
|
|
||||
|
let zip zipDir filesDir filesFilter (bundle:Bundle) = |
||||
|
CleanDir "obj/Zip" |
||||
|
let workPath = "obj/Zip/" + bundle.Id |
||||
|
CopyDir workPath filesDir filesFilter |
||||
|
provideZipExtraFiles workPath bundle |
||||
|
Zip "obj/Zip/" (zipDir </> sprintf "%s-%s.zip" bundle.Id bundle.Version) !! (workPath + "/**/*.*") |
||||
|
CleanDir "obj/Zip" |
||||
|
|
||||
|
// NUGET |
||||
|
|
||||
|
let updateNuspec (pack:Package) outPath symbols updateFiles spec = |
||||
|
{ spec with ToolPath = "packages/build/NuGet.CommandLine/tools/NuGet.exe" |
||||
|
OutputPath = outPath |
||||
|
WorkingDir = "obj/NuGet" |
||||
|
Version = pack.Version |
||||
|
ReleaseNotes = pack.ReleaseNotes |
||||
|
Project = pack.Id |
||||
|
Title = pack.Title |
||||
|
Summary = pack.Summary |
||||
|
Description = pack.Description |
||||
|
Tags = pack.Tags |
||||
|
Authors = pack.Authors |
||||
|
DependenciesByFramework = pack.Dependencies |
||||
|
SymbolPackage = symbols |
||||
|
Files = updateFiles pack.Files |
||||
|
Publish = false } |
||||
|
|
||||
|
let nugetPack bundle outPath = |
||||
|
CleanDir "obj/NuGet" |
||||
|
for pack in bundle.Packages do |
||||
|
provideNuGetExtraFiles "obj/NuGet" bundle pack |
||||
|
let withLicenseReadme f = [ "license.txt", None, None; "readme.txt", None, None; ] @ f |
||||
|
let withoutSymbolsSources f = |
||||
|
List.choose (function | (_, Some (target:string), _) when target.StartsWith("src") -> None |
||||
|
| (s, t, None) -> Some (s, t, Some ("**/*.pdb")) |
||||
|
| (s, t, Some e) -> Some (s, t, Some (e + ";**/*.pdb"))) f |
||||
|
// first pass - generates symbol + normal package. NuGet does drop the symbols from the normal package, but unfortunately not the sources. |
||||
|
NuGet (updateNuspec pack outPath NugetSymbolPackage.Nuspec withLicenseReadme) "build/MathNet.Numerics.nuspec" |
||||
|
// second pass - generate only normal package, again, but this time explicitly drop the sources (and the debug symbols) |
||||
|
NuGet (updateNuspec pack outPath NugetSymbolPackage.None (withLicenseReadme >> withoutSymbolsSources)) "build/MathNet.Numerics.nuspec" |
||||
|
CleanDir "obj/NuGet" |
||||
|
|
||||
|
let nugetPackExtension bundle outPath = |
||||
|
CleanDir "obj/NuGet" |
||||
|
for pack in bundle.Packages do |
||||
|
provideNuGetExtraFiles "obj/NuGet" bundle pack |
||||
|
let withLicenseReadme f = [ "license.txt", None, None; "readme.txt", None, None; ] @ f |
||||
|
NuGet (updateNuspec pack outPath NugetSymbolPackage.None withLicenseReadme) "build/MathNet.Numerics.Extension.nuspec" |
||||
|
CleanDir "obj/NuGet" |
||||
|
|
||||
|
|
||||
|
// -------------------------------------------------------------------------------------- |
||||
|
// Documentation |
||||
|
// -------------------------------------------------------------------------------------- |
||||
|
|
||||
|
let provideDocExtraFiles extraDocs releaseNotesDocs = |
||||
|
for (fileName, docName) in extraDocs do CopyFile ("docs/content" </> docName) fileName |
||||
|
for (fileName, docName, title) in releaseNotesDocs do |
||||
|
String.concat Environment.NewLine |
||||
|
[ "# " + title |
||||
|
"[Math.NET Numerics](ReleaseNotes.html) | [Data Extensions](ReleaseNotes-Data.html) | [MKL Native Provider](ReleaseNotes-MKL.html) | [OpenBLAS Native Provider](ReleaseNotes-OpenBLAS.html)" |
||||
|
"" |
||||
|
ReadFileAsString fileName ] |
||||
|
|> ReplaceFile ("docs/content" </> docName) |
||||
|
|
||||
|
let buildDocumentationTarget fsiargs target = |
||||
|
trace (sprintf "Building documentation (%s), this could take some time, please wait..." target) |
||||
|
let fakePath = "packages" </> "build" </> "FAKE" </> "tools" </> "FAKE.exe" |
||||
|
let fakeStartInfo script workingDirectory args fsiargs environmentVars = |
||||
|
(fun (info: System.Diagnostics.ProcessStartInfo) -> |
||||
|
info.FileName <- System.IO.Path.GetFullPath fakePath |
||||
|
info.Arguments <- sprintf "%s --fsiargs -d:FAKE %s \"%s\"" args fsiargs script |
||||
|
info.WorkingDirectory <- workingDirectory |
||||
|
let setVar k v = |
||||
|
info.EnvironmentVariables.[k] <- v |
||||
|
for (k, v) in environmentVars do |
||||
|
setVar k v |
||||
|
setVar "MSBuild" msBuildExe |
||||
|
setVar "GIT" Git.CommandHelper.gitPath |
||||
|
setVar "FSI" fsiPath) |
||||
|
let executeFAKEWithOutput workingDirectory script fsiargs envArgs = |
||||
|
let exitCode = |
||||
|
ExecProcessWithLambdas |
||||
|
(fakeStartInfo script workingDirectory "" fsiargs envArgs) |
||||
|
TimeSpan.MaxValue false ignore ignore |
||||
|
System.Threading.Thread.Sleep 1000 |
||||
|
exitCode |
||||
|
let exit = executeFAKEWithOutput "docs/tools" "build-docs.fsx" fsiargs ["target", target] |
||||
|
if exit <> 0 then |
||||
|
failwith "Generating documentation failed" |
||||
|
() |
||||
|
|
||||
|
let generateDocs fail local = |
||||
|
let args = if local then "" else "--define:RELEASE" |
||||
|
try |
||||
|
buildDocumentationTarget args "Default" |
||||
|
traceImportant "Documentation generated" |
||||
|
with |
||||
|
| e when not fail -> |
||||
|
failwith "Generating documentation failed" |
||||
|
|
||||
|
|
||||
|
// -------------------------------------------------------------------------------------- |
||||
|
// Publishing |
||||
|
// Requires permissions; intended only for maintainers |
||||
|
// -------------------------------------------------------------------------------------- |
||||
|
|
||||
|
let publishReleaseTag title prefix (release:BundleRelease) = |
||||
|
// inspired by Deedle/tpetricek |
||||
|
let tagName = prefix + "v" + release.PackageVersion |
||||
|
let tagMessage = String.concat Environment.NewLine [title + " v" + release.PackageVersion; ""; release.ReleaseNotes ] |
||||
|
let cmd = sprintf """tag -a %s -m "%s" """ tagName tagMessage |
||||
|
Git.CommandHelper.runSimpleGitCommand "." cmd |> printfn "%s" |
||||
|
let _, remotes, _ = Git.CommandHelper.runGitCommand "." "remote -v" |
||||
|
let main = remotes |> Seq.find (fun s -> s.Contains("(push)") && s.Contains("mathnet/mathnet-numerics")) |
||||
|
let remoteName = main.Split('\t').[0] |
||||
|
Git.Branches.pushTag "." remoteName tagName |
||||
|
|
||||
|
let publishNuGet packageFiles = |
||||
|
// TODO: Migrate to NuGet helper once it supports direct (non-integrated) operations |
||||
|
let rec impl trials file = |
||||
|
trace ("NuGet Push: " + System.IO.Path.GetFileName(file) + ".") |
||||
|
try |
||||
|
let args = sprintf "push \"%s\"" (FullName file) |
||||
|
let result = |
||||
|
ExecProcess (fun info -> |
||||
|
info.FileName <- "packages/build/NuGet.CommandLine/tools/NuGet.exe" |
||||
|
info.WorkingDirectory <- FullName "obj/NuGet" |
||||
|
info.Arguments <- args) (TimeSpan.FromMinutes 10.) |
||||
|
if result <> 0 then failwith "Error during NuGet push." |
||||
|
with exn -> |
||||
|
if trials > 0 then impl (trials-1) file |
||||
|
else () |
||||
|
Seq.iter (impl 3) packageFiles |
||||
|
|
||||
|
let publishMirrors () = |
||||
|
let repo = "../mirror-numerics" |
||||
|
Git.CommandHelper.runSimpleGitCommand repo "remote update" |> printfn "%s" |
||||
|
Git.CommandHelper.runSimpleGitCommand repo "push mirrors" |> printfn "%s" |
||||
|
|
||||
|
let publishDocs (release:BundleRelease) = |
||||
|
let repo = "../mathnet-websites" |
||||
|
Git.Branches.pull repo "origin" "master" |
||||
|
CopyRecursive "out/docs" "../mathnet-websites/numerics" true |> printfn "%A" |
||||
|
Git.Staging.StageAll repo |
||||
|
Git.Commit.Commit repo (sprintf "Numerics: %s docs update" release.PackageVersion) |
||||
|
Git.Branches.pushBranch repo "origin" "master" |
||||
|
|
||||
|
let publishApi (release:BundleRelease) = |
||||
|
let repo = "../mathnet-websites" |
||||
|
Git.Branches.pull repo "origin" "master" |
||||
|
CleanDir "../mathnet-websites/numerics/api" |
||||
|
CopyRecursive "out/api" "../mathnet-websites/numerics/api" true |> printfn "%A" |
||||
|
Git.Staging.StageAll repo |
||||
|
Git.Commit.Commit repo (sprintf "Numerics: %s api update" release.PackageVersion) |
||||
|
Git.Branches.pushBranch repo "origin" "master" |
||||
Loading…
Reference in new issue