forked from fable-compiler/Fable
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbuild.fsx
331 lines (284 loc) · 14.3 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
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
// 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 buildLibraryTs() =
let projectDir = "src/fable-library"
let buildDirTs = "build/fable-library-ts"
let buildDirJs = "build/fable-library-js"
cleanDirs [buildDirTs; buildDirJs]
buildSplitterWithArgs projectDir ("--typescript --classTypes --outDir " + buildDirTs)
// TODO: cleanDirs [buildDirTs </> "fable-library"]
// TODO: copy *.ts/*.js from projectDir to buildDir
runInDir buildDirTs "npx tsc --init --target es2020 --module es2020 --allowJs"
runInDir buildDirTs ("npx tsc --outDir ../../" + buildDirJs)
let quicktest additionalCommands =
cleanDirs ["build/fable-library"]
concurrently [|
// Watch fable-library
yield "npx tsc --project src/fable-library --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 src/fable-compiler/bin/fable-cli src/Fable.Cli/Fable.Cli.fsproj"
buildLibrary()
copyDirRecursive libraryDir (projectDir </> "bin/fable-library")
let buildCompilerJs() =
let projectDir = "src/fable-compiler-js"
let buildDir = "build/fable-compiler-js"
cleanDirs [buildDir; projectDir </> "dist"]
buildSplitterWithArgs projectDir ("--outDir " + buildDir + "/out")
run (sprintf "npx rollup %s/out/app.js --file %s/dist/app.js --format umd --name Fable" buildDir projectDir)
run (sprintf "npx terser %s/dist/app.js -o %s/dist/app.min.js --mangle --compress" projectDir projectDir)
let buildStandalone() =
let buildDir = "build/fable-standalone"
let libraryDir = "build/fable-library"
let projectDir = "src/fable-standalone"
let distDir = "src/fable-standalone/dist"
if pathExists libraryDir |> not then
buildLibrary()
// cleanup
cleanDirs [buildDir; distDir]
mkDirRecursive distDir
// build
buildSplitterWithArgs projectDir ("--outDir " + buildDir + "/out-bundle")
buildSplitterWithArgs (projectDir + "/src/Worker") ("--outDir " + buildDir + "/out-worker")
// bundle
run (sprintf "npx rollup %s/out-bundle/Main.js --file %s/bundle.js --format umd --name __FABLE_STANDALONE__" buildDir buildDir)
run (sprintf "npx rollup %s/out-worker/Worker.js --file %s/worker.js --format esm" buildDir buildDir)
// minimize
run (sprintf "npx terser %s/bundle.js -o %s/bundle.min.js --mangle --compress" buildDir distDir)
// run (sprintf "npx terser %s/worker.js -o %s/worker.min.js --mangle --compress" buildDir distDir)
run (sprintf "npx webpack --entry ./%s/worker.js --output ./%s/worker.min.js --config ./%s/worker.config.js" buildDir distDir projectDir)
// print bundle size
fileSizeInBytes (distDir </> "bundle.min.js") / 1000 |> printfn "Bundle size: %iKB"
fileSizeInBytes (distDir </> "worker.min.js") / 1000 |> printfn "Worker size: %iKB"
// Put fable-library files next to bundle
let libraryTarget = distDir </> "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 testJs() =
let projectDir = "src/fable-compiler-js"
let buildDir = "build/tests-js"
if not (pathExists "build/fable-standalone") then
buildStandalone()
if not (pathExists "build/fable-compiler-js") then
buildCompilerJs()
cleanDirs [buildDir]
// Link fable-compiler-js to local packages
runInDir projectDir "npm link ../fable-metadata"
runInDir projectDir "npm link ../fable-standalone"
// Test fable-compiler-js locally
run ("node " + projectDir + " tests/Main/Fable.Tests.fsproj " + buildDir + " --commonjs")
run ("npx mocha " + buildDir + " --reporter dot -t 10000")
// and another test
runInDir "src/fable-compiler-js/test" "node .. test_script.fsx --commonjs"
runInDir "src/fable-compiler-js/test" "node bin/test_script.js"
// Unlink local packages after test
runInDir projectDir "npm unlink ../fable-metadata && cd ../fable-metadata && npm unlink"
runInDir projectDir "npm unlink ../fable-standalone && cd ../fable-standalone && npm unlink"
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"
if envVarOrNone "APPVEYOR" |> Option.isSome then
testJs()
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", buildCompilerJs
"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()
| "test-js"::_ -> testJs()
| "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-library-ts"|"library-ts")::_ -> buildLibraryTs()
| ("fable-compiler"|"compiler")::_ -> buildCompiler()
| ("fable-compiler-js"|"compiler-js")::_ -> buildCompilerJs()
| ("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"