-
Notifications
You must be signed in to change notification settings - Fork 311
/
Copy pathbuild.fsx
290 lines (249 loc) · 12.2 KB
/
build.fsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
// This script is compiled by fable-compiler-js and runs entirely on node.js
// You can execute it by typing: npx fable build.fsx --run [ARGUMENTS]
#r "src/fable-metadata/lib/Fable.Core.dll"
#load "src/fable-publish-utils/PublishUtils.fs"
open PublishUtils
open System
open System.Text.RegularExpressions
open Fable.Core
open Fable.Core.JsInterop
// Appveyor artifact
let FABLE_BRANCH = "master"
let APPVEYOR_REPL_ARTIFACT_URL_PARAMS = "?branch=" + FABLE_BRANCH + "&pr=false"
let APPVEYOR_REPL_ARTIFACT_URL =
"https://ci.appveyor.com/api/projects/fable-compiler/Fable/artifacts/src/fable-standalone/fable-standalone.zip"
+ APPVEYOR_REPL_ARTIFACT_URL_PARAMS
// ncave FCS fork
let FCS_REPO = "https://github.com/ncave/fsharp"
let FCS_REPO_LOCAL = "../fsharp_fable"
let FCS_REPO_FABLE_BRANCH = "fable"
let FCS_REPO_SERVICE_SLIM_BRANCH = "service_slim"
type GhRealeases =
[<Emit("""new Promise((succeed, fail) =>
$0.create({user: $1, token: $2}, $3, $4, { tag_name: $5, name: $5, body: $6 }, (err, res) =>
err != null ? fail(err) : succeed(res)))""")>]
abstract create: user: string * token: string * owner: string * repo: string * name: string * msg: string -> JS.Promise<obj>
let concurrently(commands: string[]): unit = importDefault "concurrently"
let cleanDirs dirs =
for dir in dirs do
removeDirRecursive dir
let updateVersionInCliUtil() =
let filePath = "src/Fable.Cli/Util.fs"
let version = Publish.loadReleaseVersion "src/fable-compiler"
// printfn "VERSION %s" version
Regex.Replace(
readFile filePath,
@"let \[<Literal>] VERSION = "".*?""",
sprintf "let [<Literal>] VERSION = \"%s\"" version)
|> writeFile filePath
let downloadAndExtractTo (url: string) (targetDir: string) =
sprintf "npx download --extract --out %s \"%s\"" targetDir url |> run
let buildTypescript projectDir =
// run ("npx tslint --project " + projectDir)
run ("npx tsc --project " + projectDir)
let buildSplitterWithArgs projectDir args =
run ("npx fable-splitter -c " + (projectDir </> "splitter.config.js") + " " + args)
let buildSplitter projectDir =
buildSplitterWithArgs projectDir ""
let buildWebpack projectDir =
run ("npx webpack --config " + (projectDir </> "webpack.config.js"))
let buildLibrary() =
cleanDirs ["build/fable-library"]
buildTypescript "src/fable-library"
buildSplitter "src/fable-library"
let quicktest additionalCommands =
cleanDirs ["build/fable-library"]
concurrently [|
// Watch fable-library
yield "npx tsc --project src/fable-library --watch"
yield "npx fable-splitter -c src/fable-library/splitter.config.js --watch"
// Restart splitter on changes so latest fable-library and compiler are picked
yield "npx nodemon --watch src/quicktest -e \"fs\" --exec \"fable-splitter -c src/quicktest/splitter.config.js --run\""
yield! additionalCommands
|]
let buildCompiler() =
let projectDir = "src/fable-compiler"
let libraryDir = "build/fable-library"
cleanDirs [projectDir </> "dist"; projectDir </> "bin"]
buildTypescript projectDir
updateVersionInCliUtil()
run "dotnet publish -c Release -o ../fable-compiler/bin/fable-cli src/Fable.Cli/Fable.Cli.fsproj"
buildLibrary()
copyDirRecursive libraryDir (projectDir </> "bin/fable-library")
let buildCompilerJs testLocal =
let projectDir = "src/fable-compiler-js"
cleanDirs [projectDir </> "dist"]
if testLocal then
buildSplitterWithArgs projectDir "--test-local"
else
buildSplitter projectDir
let buildStandalone() =
let projectDir = "src/fable-standalone"
let libraryDir = "build/fable-library"
if pathExists libraryDir |> not then
buildLibrary()
cleanDirs [projectDir </> "dist"]
// bundle.min.js
buildWebpack projectDir
fileSizeInBytes (projectDir </> "dist/bundle.min.js") / 1000
|> printfn "Bundle size: %iKB"
// worker.min.js
buildWebpack "src/fable-standalone/src/Worker"
// Put fable-library files next to bundle
let libraryTarget = projectDir </> "dist/fable-library"
copyDirRecursive libraryDir libraryTarget
// These files will be used in the browser, so make sure the import paths include .js extension
let reg = Regex(@"^import (.*"".*)("".*)$", RegexOptions.Multiline)
getFullPathsInDirectoryRecursively libraryTarget
|> Array.filter (fun file -> file.EndsWith(".js"))
|> Array.iter (fun file ->
reg.Replace(readFile file, fun m ->
let fst = m.Groups.[1].Value
if fst.EndsWith(".js") then m.Value
else sprintf "import %s.js%s" fst m.Groups.[2].Value)
|> writeFile file)
// Bump version
// let compilerVersion = Publish.loadReleaseVersion "src/fable-compiler"
// let standaloneVersion = Publish.loadNpmVersion projectDir
// let (comMajor, comMinor, _, comPrerelease) = Publish.splitVersion compilerVersion
// let (staMajor, staMinor, staPatch, _) = Publish.splitVersion standaloneVersion
// Publish.bumpNpmVersion projectDir
// (if comMajor > staMajor || comMinor > staMinor then compilerVersion
// else sprintf "%i.%i.%i%s" staMajor staMinor (staPatch + 1) comPrerelease)
let test() =
if pathExists "build/fable-library" |> not then
buildLibrary()
cleanDirs ["build/tests"]
buildSplitter "tests"
run "npx mocha build/tests --reporter dot -t 10000"
runInDir "tests/Main" "dotnet run"
runInDir "tests/Fable.Cli.Test" "dotnet run"
if envVarOrNone "APPVEYOR" |> Option.isSome then
buildStandalone()
// Test fable-compiler-js locally
buildCompilerJs true
run "node src/fable-compiler-js tests/Main/Fable.Tests.fsproj build/tests-js --commonjs"
run "npx mocha build/tests-js --reporter dot -t 10000"
// runInDir "src/fable-compiler-js/test" "node .. test_script.fsx --commonjs"
// runInDir "src/fable-compiler-js/test" "node bin/test_script.js"
let coverage() =
// report converter
// https://github.com/danielpalme/ReportGenerator
// dotnet tool install dotnet-reportgenerator-globaltool --tool-path tools
if not (pathExists "./bin/tools/reportgenerator") && not (pathExists "./bin/tools/reportgenerator.exe") then
runInDir "." "dotnet tool install dotnet-reportgenerator-globaltool --tool-path bin/tools"
let reportGen =
if pathExists "./bin/tools/reportgenerator" then "bin/tools/reportgenerator"
else "bin\\tools\\reportgenerator.exe"
if pathExists "build/fable-library" |> not then
buildLibrary()
cleanDirs ["build/tests"]
buildSplitter "tests"
// JS
run "npx nyc mocha build/tests --require source-map-support/register --reporter dot -t 10000"
runInDir "." (reportGen + " \"-reports:build/coverage/nyc/lcov.info\" -reporttypes:Html \"-targetdir:build/coverage/nyc/html\" ")
// .NET
//runInDir "tests/Main" "dotnet build /t:Collect_Coverage"
cleanDirs ["build/coverage/netcoreapp2.0/out"]
runInDir "." (reportGen + " \"-reports:build/coverage/netcoreapp2.0/coverage.xml\" -reporttypes:Html \"-targetdir:build/coverage/netcoreapp2.0/html\" ")
let downloadStandalone() =
let targetDir = "src/fable-standalone/dist"
cleanDirs [targetDir]
downloadAndExtractTo APPVEYOR_REPL_ARTIFACT_URL targetDir
// TODO: Run fable-splitter tests
let buildFableSplitter() =
buildTypescript "src/fable-splitter"
let githubRelease() =
match envVarOrNone "GITHUB_USER", envVarOrNone "GITHUB_TOKEN" with
| Some user, Some token ->
async {
try
let ghreleases: GhRealeases = JsInterop.importAll "ghreleases"
let! version, notes = Publish.loadReleaseVersionAndNotes "src/fable-compiler"
run <| sprintf "git commit -am \"Release %s\" && git push" version
let! res = ghreleases.create(user, token, "fable-compiler", "Fable", version, String.concat "\n" notes) |> Async.AwaitPromise
printfn "Github release %s created successfully" version
with ex ->
printfn "Github release failed: %s" ex.Message
} |> Async.StartImmediate
| _ -> failwith "Expecting GITHUB_USER and GITHUB_TOKEN enviromental variables"
let syncFcsRepo() =
// FAKE is giving lots of problems with the dotnet SDK version, ignore it
let cheatWithDotnetSdkVersion dir f =
let path = dir </> "build.fsx"
let script = readFile path
Regex.Replace(script, @"let dotnetExePath =[\s\S]*DotNetCli\.InstallDotNetSDK", "let dotnetExePath = \"dotnet\" //DotNetCli.InstallDotNetSDK") |> writeFile path
f ()
runInDir dir "git reset --hard"
printfn "Expecting %s repo to be cloned at %s" FCS_REPO FCS_REPO_LOCAL
// TODO: Prompt to reset --hard changes
// service_slim
runInDir FCS_REPO_LOCAL ("git checkout " + FCS_REPO_SERVICE_SLIM_BRANCH)
runInDir FCS_REPO_LOCAL "git pull"
cheatWithDotnetSdkVersion (FCS_REPO_LOCAL </> "fcs") (fun () ->
runBashOrCmd (FCS_REPO_LOCAL </> "fcs") "build" "")
copyFile (FCS_REPO_LOCAL </> "artifacts/bin/fcs/Release/netstandard2.0/FSharp.Compiler.Service.dll") "../fable/lib/fcs/"
copyFile (FCS_REPO_LOCAL </> "artifacts/bin/fcs/Release/netstandard2.0/FSharp.Compiler.Service.xml") "../fable/lib/fcs/"
// fcs-fable
runInDir FCS_REPO_LOCAL ("git checkout " + FCS_REPO_FABLE_BRANCH)
runInDir FCS_REPO_LOCAL "git pull"
cheatWithDotnetSdkVersion (FCS_REPO_LOCAL </> "fcs") (fun () ->
runBashOrCmd (FCS_REPO_LOCAL </> "fcs") "build" "CodeGen.Fable")
copyDirRecursive (FCS_REPO_LOCAL </> "fcs/fcs-fable") "src/fcs-fable"
copyDirNonRecursive (FCS_REPO_LOCAL </> "src/absil") "src/fcs-fable/src/absil"
copyDirNonRecursive (FCS_REPO_LOCAL </> "src/fsharp") "src/fcs-fable/src/fsharp"
copyDirNonRecursive (FCS_REPO_LOCAL </> "src/fsharp/service") "src/fcs-fable/src/fsharp/service"
copyDirNonRecursive (FCS_REPO_LOCAL </> "src/fsharp/symbols") "src/fcs-fable/src/fsharp/symbols"
copyDirNonRecursive (FCS_REPO_LOCAL </> "src/ilx") "src/fcs-fable/src/ilx"
copyDirNonRecursive (FCS_REPO_LOCAL </> "src/utils") "src/fcs-fable/src/utils"
removeFile "src/fcs-fable/.gitignore"
let fcsFableProj = "src/fcs-fable/fcs-fable.fsproj"
Regex.Replace(
readFile fcsFableProj,
@"(<FSharpSourcesRoot>\$\(MSBuildProjectDirectory\)).*?(<\/FSharpSourcesRoot>)",
"$1/src$2")
|> writeFile fcsFableProj
let packages =
["Fable.Core", doNothing
"fable-babel-plugins", doNothing
"fable-compiler", buildCompiler
"fable-compiler-js", (fun () -> buildCompilerJs false)
"fable-loader", doNothing
"fable-metadata", doNothing
"fable-publish-utils", doNothing
"fable-splitter", buildFableSplitter
"fable-standalone", downloadStandalone
]
let publishPackages restArgs =
let packages =
match List.tryHead restArgs with
| Some pkg -> packages |> List.filter (fun (name,_) -> name = pkg)
| None -> packages
for (pkg, buildAction) in packages do
if System.Char.IsUpper pkg.[0] then
pushNuget ("src" </> pkg </> pkg + ".fsproj") buildAction
else
pushNpm ("src" </> pkg) buildAction
match argsLower with
| "test"::_ -> test()
| "coverage"::_ -> coverage()
| "quicktest-fast"::_ -> run "npx fable-splitter -c src/quicktest/splitter.config.js --watch --run"
| "quicktest"::_ -> quicktest []
| "check-sourcemaps"::_ ->
("src/quicktest/Quicktest.fs", "src/quicktest/bin/Quicktest.js", "src/quicktest/bin/Quicktest.js.map")
|||> sprintf "nodemon --watch src/quicktest/bin/Quicktest.js --exec 'source-map-visualization --sm=\"%s;%s;%s\"'"
|> List.singleton |> quicktest
| ("fable-library"|"library")::_ -> buildLibrary()
| ("fable-compiler"|"compiler")::_ -> buildCompiler()
| ("fable-compiler-js"|"compiler-js")::_ -> buildCompilerJs false
| ("fable-splitter"|"splitter")::_ -> buildFableSplitter()
| ("fable-standalone"|"standalone")::_ -> buildStandalone()
| "download-standalone"::_ -> downloadStandalone()
| "publish"::restArgs -> publishPackages restArgs
| "github-release"::_ ->
publishPackages []
githubRelease ()
| "sync-fcs-repo"::_ -> syncFcsRepo()
| _ ->
printfn "Please pass a target name"
printf "Build finished successfully"