Skip to content

Commit 6f5ad39

Browse files
Improvements to CLI (#2183)
* CLI improvements * Make cli args consistent and other fixes
1 parent a15d9d8 commit 6f5ad39

File tree

6 files changed

+143
-116
lines changed

6 files changed

+143
-116
lines changed

build.fsx

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ let buildLibrary() =
7676

7777
runFableWithArgs projectDir [
7878
"--outDir " + buildDir
79-
"--fable-library " + buildDir
79+
"--fableLib " + buildDir
8080
"--exclude Fable.Core"
8181
"--define FX_NO_BIGINT"
8282
]
@@ -116,7 +116,7 @@ let buildLibraryTs() =
116116

117117
runFableWithArgs projectDir [
118118
"--outDir " + buildDirTs
119-
"--fable-library " + buildDirTs
119+
"--fableLib " + buildDirTs
120120
"--typescript"
121121
"--exclude Fable.Core"
122122
"--define FX_NO_BIGINT"
@@ -136,7 +136,7 @@ let quicktest () =
136136
writeFile quicktestJsPath "console.log('Getting ready, hold tight')"
137137

138138
concurrently [|
139-
"dotnet watch -p src/Fable.Cli run -- watch --cwd ../quicktest --exclude Fable.Core --force-pkgs"
139+
"dotnet watch -p src/Fable.Cli run -- watch --cwd ../quicktest --exclude Fable.Core --forcePkgs"
140140
"npx nodemon " + quicktestJsPath
141141
|]
142142

@@ -156,9 +156,9 @@ let buildStandalone() =
156156
// build standalone bundle
157157
runFableWithArgs projectDir [
158158
"--outDir " + buildDir + "/bundle"
159-
"--fable-library " + libraryDir
160-
"--force-pkgs"
161-
"--typed-arrays"
159+
"--fableLib " + libraryDir
160+
"--forcePkgs"
161+
"--typedArrays"
162162
"--define FX_NO_CORHOST_SIGNER"
163163
"--define FX_NO_LINKEDRESOURCES"
164164
"--define FX_NO_PDB_READER"
@@ -173,8 +173,8 @@ let buildStandalone() =
173173
// build standalone worker
174174
runFableWithArgs (projectDir + "/Worker") [
175175
"--outDir " + buildDir + "/worker"
176-
"--fable-library " + libraryDir
177-
"--force-pkgs"
176+
"--fableLib " + libraryDir
177+
"--forcePkgs"
178178
]
179179

180180
// make standalone bundle dist
@@ -227,8 +227,8 @@ let buildCompilerJs() =
227227

228228
runFableWithArgs projectDir [
229229
"--outDir " + buildDir
230-
"--fable-library " + libraryDir
231-
"--force-pkgs"
230+
"--fableLib " + libraryDir
231+
"--forcePkgs"
232232
"--exclude Fable.Core"
233233
]
234234

@@ -275,8 +275,8 @@ let test() =
275275

276276
runFableWithArgs projectDir [
277277
"--outDir " + buildDir
278-
"--fable-library " + libraryDir
279-
"--force-pkgs"
278+
"--fableLib " + libraryDir
279+
"--forcePkgs"
280280
"--exclude Fable.Core"
281281
]
282282

src/Fable.Cli/Entry.fs

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -33,19 +33,21 @@ Commands:
3333
clean Clean generated JS files
3434
3535
Arguments:
36+
--cwd Working directory
3637
--outDir Redirect compilation output files to a directory
3738
--define Defines a symbol for use in conditional compilation
39+
--run The command after the argument will be executed after compilation
40+
--runWatch Like run, but will execute after each watch compilation
41+
--typedArrays Compile numeric arrays to JS typed arrays
42+
--forcePkgs Force a new copy of package sources into `.fable` folder
3843
--extension Extension for generated JS files (default .fs.js)
3944
--verbose Print more info during compilation
4045
--exclude Skip Fable compilation for files containing the pattern
41-
--typed-arrays Compile numeric arrays to JS typed arrays
42-
--force-pkgs Force a new copy of package sources into `.fable` folder
4346
--optimize Use optimized AST from F# compiler (experimental)
44-
--cwd Working directory
4547
"""
4648

4749
type Runner =
48-
static member Run(args: string list, rootDir: string, ?fsprojPath, ?watch, ?testInfo) =
50+
static member Run(args: string list, rootDir: string, runArgs: RunArgs option, ?fsprojPath, ?watch, ?testInfo) =
4951
let watch = defaultArg watch false
5052

5153
fsprojPath
@@ -75,26 +77,30 @@ type Runner =
7577

7678
let defines =
7779
argValues "--define" args
78-
|> List.append ["FABLE_COMPILER"]
80+
|> List.append [
81+
"FABLE_COMPILER"
82+
if watch then "DEBUG"
83+
]
7984
|> List.distinct
8085
|> List.toArray
8186

8287
let compilerOptions =
8388
CompilerOptionsHelper.Make(typescript = hasFlag "--typescript" args,
84-
typedArrays = hasFlag "--typed-arrays" args,
89+
typedArrays = hasFlag "--typedArrays" args,
8590
?fileExtension = argValue "--extension" args,
8691
debugMode = Array.contains "DEBUG" defines,
8792
optimizeFSharpAst = hasFlag "--optimize" args,
8893
verbosity = verbosity)
8994

9095
let cliArgs =
9196
{ ProjectFile = projFile
92-
FableLibraryPath = argValue "--fable-library" args
97+
FableLibraryPath = argValue "--fableLib" args
9398
RootDir = rootDir
9499
OutDir = argValue "--outDir" args
95-
ForcePackages = hasFlag "--force-pkgs" args
100+
ForcePackages = hasFlag "--forcePkgs" args
96101
Exclude = argValue "--exclude" args
97102
Define = defines
103+
RunArgs = runArgs
98104
CompilerOptions = compilerOptions }
99105

100106
let watcher =
@@ -123,6 +129,11 @@ let clean args dir =
123129
|> Option.defaultValue CompilerOptionsHelper.DefaultFileExtension
124130

125131
let rec recClean dir =
132+
IO.Directory.GetDirectories(dir)
133+
|> Array.iter (fun subdir ->
134+
if IO.Path.GetDirectoryName(subdir) = Naming.fableHiddenDir then
135+
IO.Directory.Delete(subdir, true))
136+
126137
IO.Directory.GetFiles(dir)
127138
|> Array.choose (fun file ->
128139
if file.EndsWith(".fs") then Some(file.[.. (file.Length - 4)])
@@ -131,8 +142,7 @@ let clean args dir =
131142
let file = filename + ext
132143
if IO.File.Exists(file) then
133144
IO.File.Delete(file)
134-
Log.verbose(lazy ("Deleted " + file))
135-
)
145+
Log.verbose(lazy ("Deleted " + file)))
136146

137147
IO.Directory.GetDirectories(dir)
138148
|> Array.filter (fun subdir ->
@@ -148,7 +158,15 @@ let (|SplitCommandArgs|) (xs: string list) =
148158

149159
[<EntryPoint>]
150160
let main argv =
151-
let argv = List.ofArray argv
161+
let argv, runArgs =
162+
argv
163+
|> List.ofArray
164+
|> List.splitWhile (fun a -> not(a.StartsWith("--run")))
165+
|> function
166+
| argv, flag::exeFile::runArgs ->
167+
argv, Some(RunArgs(exeFile, runArgs, watch=(flag = "--runWatch")))
168+
| argv, _ -> argv, None
169+
152170
let rootDir =
153171
match argValue "--cwd" argv with
154172
| Some rootDir -> IO.Path.GetFullPath(rootDir)
@@ -165,9 +183,9 @@ let main argv =
165183
match commands with
166184
| ["clean"; dir] -> clean args dir
167185
| ["clean"] -> clean args rootDir
168-
| ["test"; path] -> Runner.Run(args, rootDir, fsprojPath=path, testInfo=TestInfo())
169-
| ["watch"; path] -> Runner.Run(args, rootDir, fsprojPath=path, watch=true)
170-
| ["watch"] -> Runner.Run(args, rootDir, watch=true)
171-
| [path] -> Runner.Run(args, rootDir, fsprojPath=path)
172-
| [] -> Runner.Run(args, rootDir)
186+
| ["test"; path] -> Runner.Run(args, rootDir, runArgs, fsprojPath=path, testInfo=TestInfo())
187+
| ["watch"; path] -> Runner.Run(args, rootDir, runArgs, fsprojPath=path, watch=true)
188+
| ["watch"] -> Runner.Run(args, rootDir, runArgs, watch=true)
189+
| [path] -> Runner.Run(args, rootDir, runArgs, fsprojPath=path)
190+
| [] -> Runner.Run(args, rootDir, runArgs)
173191
| _ -> printfn "Unexpected arguments. Use `fable --help` to see available options."; 1

src/Fable.Cli/Main.fs

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -97,13 +97,13 @@ module private Util =
9797
// else printfn "Fable.Core version matches"
9898

9999
let measureTime (f: unit -> 'a) =
100-
let sw = System.Diagnostics.Stopwatch.StartNew()
100+
let sw = Diagnostics.Stopwatch.StartNew()
101101
let res = f()
102102
sw.Stop()
103103
res, sw.ElapsedMilliseconds
104104

105105
let measureTimeAsync (f: unit -> Async<'a>) = async {
106-
let sw = System.Diagnostics.Stopwatch.StartNew()
106+
let sw = Diagnostics.Stopwatch.StartNew()
107107
let! res = f()
108108
sw.Stop()
109109
return res, sw.ElapsedMilliseconds
@@ -191,7 +191,7 @@ module private Util =
191191
let writer = new FileWriter(com.CurrentFile, outPath, projDir, cliArgs.OutDir)
192192
do! BabelPrinter.run writer map babel
193193

194-
Log.always("Compiled " + Path.getRelativePath cliArgs.RootDir com.CurrentFile)
194+
Log.always("Compiled " + File.getRelativePathFromCwd com.CurrentFile)
195195

196196
return Ok {| File = com.CurrentFile
197197
Logs = com.Logs
@@ -243,7 +243,7 @@ type ProjectCracked(sourceFiles: File array,
243243
}
244244

245245
Log.verbose(lazy
246-
let proj = Path.getRelativePath msg.RootDir msg.ProjectFile
246+
let proj = File.getRelativePathFromCwd msg.ProjectFile
247247
let opts = projectOptions.OtherOptions |> String.concat "\n "
248248
sprintf "F# PROJECT: %s\n %s" proj opts)
249249

@@ -264,7 +264,7 @@ type ProjectParsed(project: Project,
264264
Log.always("Initializing F# compiler...")
265265
InteractiveChecker.Create(config.ProjectOptions)
266266

267-
Log.always("Compiling " + Path.getRelativePath cliArgs.RootDir config.ProjectFile + "...")
267+
Log.always("Compiling " + File.getRelativePathFromCwd config.ProjectFile + "...")
268268

269269
let checkedProject, ms = measureTime <| fun () ->
270270
let fileDic = config.SourceFiles |> Seq.map (fun f -> f.NormalizedFullPath, f) |> dict
@@ -342,7 +342,6 @@ let rec startCompilation (changes: Set<string>) (state: State) = async {
342342
File(file.NormalizedFullPath) // Clear the cached source hash
343343
else file)
344344
let parsed = ProjectParsed.Init(state.CliArgs, cracked, parsed.Checker)
345-
// TODO: We probably need to recompile errored files too even if they're not touched
346345
let filesToCompile =
347346
cracked.SourceFiles
348347
|> Array.choose (fun file ->
@@ -357,6 +356,15 @@ let rec startCompilation (changes: Set<string>) (state: State) = async {
357356
let filesToCompile =
358357
cracked.SourceFiles
359358
|> Array.map (fun f -> f.NormalizedFullPath)
359+
// Skip files that have a more recent JS version
360+
|> fun files ->
361+
if Option.isSome state.CliArgs.OutDir then files
362+
else
363+
files |> Array.skipWhile (fun file ->
364+
try
365+
let jsFile = Path.replaceExtension state.CliArgs.CompilerOptions.FileExtension file
366+
File.Exists(jsFile) && File.GetLastWriteTime(jsFile) > File.GetLastWriteTime(file)
367+
with _ -> false)
360368
cracked, parsed, filesToCompile
361369

362370
let filesToCompile =
@@ -411,13 +419,21 @@ let rec startCompilation (changes: Set<string>) (state: State) = async {
411419
| Some file -> Set.add file errors
412420
| None -> errors) Set.empty
413421

422+
let state =
423+
match state.CliArgs.RunArgs with
424+
| Some runArgs ->
425+
Process.fireAndForget state.CliArgs.RootDir runArgs.ExeFile runArgs.Args
426+
if runArgs.IsWatch then state
427+
else { state with CliArgs = { state.CliArgs with RunArgs = None } }
428+
| None -> state
429+
414430
match state.Watcher, state.TestInfo with
415431
| Some watcher, _ ->
416432
let oldErrors =
417433
state.ErroredFiles
418434
|> Set.filter (fun file -> not(Array.contains file filesToCompile))
419435

420-
Log.always("Watching " + Path.getRelativePath state.CliArgs.RootDir watcher.Directory)
436+
Log.always("Watching " + File.getRelativePathFromCwd watcher.Directory)
421437
let! changes = watcher.AwaitChanges()
422438
return!
423439
{ state with ProjectCrackedAndParsed = Some(cracked, parsed)

src/Fable.Cli/ProjectCracker.fs

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -245,12 +245,12 @@ let fullCrack (opts: Options): CrackedFsproj =
245245
let dllRefs = Dictionary(StringComparer.OrdinalIgnoreCase)
246246

247247
// Try restoring project
248-
Process.runCmd Log.always
249-
(IO.Path.GetDirectoryName projFile)
250-
"dotnet" ["restore"; IO.Path.GetFileName projFile]
248+
let projDir = IO.Path.GetDirectoryName projFile
249+
let projName = IO.Path.GetFileName projFile
250+
Process.runSync projDir "dotnet" ["restore"; projName]
251251
|> ignore
252252

253-
Log.always("Parsing " + Path.getRelativePath opts.rootDir projFile + "...")
253+
Log.always("Parsing " + File.getRelativePathFromCwd projFile + "...")
254254
let projOpts, projRefs, _msbuildProps =
255255
ProjectCoreCracker.GetProjectOptionsFromProjectFile projFile
256256

@@ -367,9 +367,25 @@ let isDirectoryEmpty dir =
367367

368368
let createFableDir rootDir =
369369
let fableDir = IO.Path.Combine(rootDir, Naming.fableHiddenDir)
370-
if isDirectoryEmpty fableDir then
370+
let compilerInfo = IO.Path.Combine(fableDir, "compiler_info.txt")
371+
372+
let isEmptyOrOutdated =
373+
if isDirectoryEmpty fableDir then true
374+
else
375+
let isOutdated =
376+
try
377+
let version = IO.File.ReadAllText(compilerInfo)
378+
version <> Literals.VERSION
379+
with _ -> true
380+
if isOutdated then
381+
IO.Directory.Delete(fableDir, true)
382+
isOutdated
383+
384+
if isEmptyOrOutdated then
371385
IO.Directory.CreateDirectory(fableDir) |> ignore
386+
IO.File.WriteAllText(compilerInfo, Literals.VERSION)
372387
IO.File.WriteAllText(IO.Path.Combine(fableDir, ".gitignore"), "**/*")
388+
373389
fableDir
374390

375391
let copyDirIfDoesNotExist (opts: Options) (source: string) (target: string) =

0 commit comments

Comments
 (0)