53 lines
1.9 KiB
Text
53 lines
1.9 KiB
Text
/-
|
||
Copyright (c) 2017 Microsoft Corporation. All rights reserved.
|
||
Released under Apache 2.0 license as described in the file LICENSE.
|
||
Authors: Gabriel Ebner, Sebastian Ullrich, Mac Malone
|
||
-/
|
||
import Leanpkg2.Package
|
||
import Leanpkg2.BuildConfig
|
||
|
||
open System
|
||
|
||
namespace Leanpkg2
|
||
|
||
def lockFileName : FilePath := ".leanpkg-lock"
|
||
|
||
partial def withLockFile (x : IO α) : IO α := do
|
||
acquire
|
||
try
|
||
x
|
||
finally
|
||
IO.removeFile lockFileName
|
||
where
|
||
acquire (firstTime := true) :=
|
||
try
|
||
-- TODO: lock file should ideally contain PID
|
||
if !Platform.isWindows then
|
||
discard <| IO.Prim.Handle.mk lockFileName "wx"
|
||
else
|
||
-- `x` mode doesn't seem to work on Windows even though it's listed at
|
||
-- https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/fopen-wfopen?view=msvc-160
|
||
-- ...? Let's use the slightly racy approach then.
|
||
if ← lockFileName.pathExists then
|
||
throw <| IO.Error.alreadyExists 0 ""
|
||
discard <| IO.Prim.Handle.mk lockFileName "w"
|
||
catch
|
||
| IO.Error.alreadyExists _ _ => do
|
||
if firstTime then
|
||
IO.eprintln s!"Waiting for prior leanpkg invocation to finish... (remove '{lockFileName}' if stuck)"
|
||
IO.sleep (ms := 300)
|
||
acquire (firstTime := false)
|
||
| e => throw e
|
||
|
||
def execMake (manifest : Manifest) (makeArgs : List String) (cfg : BuildConfig) : IO Unit := withLockFile do
|
||
let timeoutArgs :=
|
||
match manifest.timeout with
|
||
| some t => ["-T", toString t]
|
||
| none => []
|
||
let leanArgs := timeoutArgs ++ cfg.leanArgs
|
||
let mut spawnArgs := {
|
||
cmd := "sh"
|
||
cwd := manifest.effectivePath
|
||
args := #["-c", s!"\"{← IO.appDir}/leanmake\" PKG={cfg.module} LEAN_OPTS=\"{" ".intercalate leanArgs}\" LEAN_PATH=\"{cfg.leanPath}\" {" ".intercalate makeArgs} MORE_DEPS+=\"{" ".intercalate (cfg.moreDeps.map toString)}\" >&2"]
|
||
}
|
||
execCmd spawnArgs
|