summaryrefslogtreecommitdiff
path: root/Biz/Bild.hs
diff options
context:
space:
mode:
authorBen Sima <ben@bsima.me>2022-08-03 10:44:09 -0400
committerBen Sima <ben@bsima.me>2022-08-03 10:44:09 -0400
commit15a6bb53c7aed9cbf6f1a8edb1b8dbbd174cf9f5 (patch)
treed0b0fece0bbab6e8c5315acccafdb2dcbd76645e /Biz/Bild.hs
parent5ed01579afe46f14ee999b7d2d8be18d6f7d347e (diff)
Add compilerFlags to Target
This moves logic into the analysis step, and allows better auditing because you can see exactly what flags and command bild will use to compile the target.
Diffstat (limited to 'Biz/Bild.hs')
-rw-r--r--Biz/Bild.hs317
1 files changed, 160 insertions, 157 deletions
diff --git a/Biz/Bild.hs b/Biz/Bild.hs
index b23a8ff..f23d04a 100644
--- a/Biz/Bild.hs
+++ b/Biz/Bild.hs
@@ -197,8 +197,8 @@ exitSummary exits =
type Dep = String
-data Out = Lib String | Bin String
- deriving (Show)
+data Out = Lib String | Bin String | None
+ deriving (Show, Eq)
instance Aeson.ToJSON Out where
toJSON out = outdir out |> Text.pack |> Aeson.String
@@ -212,11 +212,23 @@ data Compiler
| NixBuild
| Rustc
| Sbcl
- deriving (Eq, Show, Generic, Aeson.ToJSON)
+ deriving (Eq, Show, Generic)
+
+instance Aeson.ToJSON Compiler where
+ toJSON =
+ Aeson.String <. \case
+ Copy -> "cp"
+ Gcc -> "gcc"
+ GhcLib -> "ghc"
+ GhcExe -> "ghc"
+ Guile -> "guile"
+ NixBuild -> "nix-build"
+ Rustc -> "rustc"
+ Sbcl -> "sbcl"
data Target = Target
{ -- | Output name
- out :: Maybe Out,
+ out :: Out,
-- | Fully qualified namespace partitioned by '.'
namespace :: Namespace,
-- | Absolute path to file
@@ -228,7 +240,9 @@ data Target = Target
-- | Which compiler should we use?
compiler :: Compiler,
-- | Where is this machine being built? Schema: user@location
- builder :: Text
+ builder :: Text,
+ -- | Flags and arguments passed to 'Compiler' when building
+ compilerFlags :: [Text]
}
deriving (Show, Generic, Aeson.ToJSON)
@@ -264,6 +278,7 @@ outdir :: Out -> String
outdir = \case
Bin o -> "_/bin" </> o
Lib o -> "_/lib" </> o
+ None -> mempty
intdir, nixdir, vardir :: String
intdir = "_/int"
@@ -316,25 +331,41 @@ analyze path = do
Namespace.None -> pure Nothing
Namespace.Py -> pure Nothing
Namespace.Sh -> pure Nothing
- Namespace.C ->
+ Namespace.C -> do
+ let out =
+ contentLines
+ /> Text.unpack
+ /> Regex.match (metaOut "//" <|> metaLib "//")
+ |> catMaybes
+ |> head
+ |> fromMaybe None
+ let sysdeps =
+ contentLines
+ /> Text.unpack
+ /> Regex.match (metaSys "//")
+ |> catMaybes
+ |> Set.fromList
+ guileFlags <-
+ if "guile_3_0" `elem` sysdeps
+ then
+ Process.readProcess "guile-config" ["compile"] ""
+ /> String.words
+ /> (++ ["-shared", "-fPIC"])
+ /> map Text.pack
+ else pure mempty
Just
</ pure
Target
{ langdeps = Set.empty, -- c has no lang deps...?
- sysdeps =
- contentLines
- /> Text.unpack
- /> Regex.match (metaSys "//")
- |> catMaybes
- |> Set.fromList,
compiler = Gcc,
- out =
- contentLines
- /> Text.unpack
- /> Regex.match (metaOut "//" <|> metaLib "//")
- |> catMaybes
- |> head,
builder = user <> "@localhost",
+ compilerFlags =
+ concat
+ [ [o, dir, Text.pack absPath] ++ guileFlags
+ | let outable = out /= None,
+ o <- outable ?: (["-o"], []),
+ dir <- outable ?: ([Text.pack <| root </> outdir out], [])
+ ],
..
}
Namespace.Hs -> do
@@ -345,11 +376,34 @@ analyze path = do
/> Regex.match (metaOut "--")
|> catMaybes
|> head
+ |> fromMaybe None
Just
</ pure
Target
{ builder = user <> "@localhost",
compiler = detectGhcCompiler out,
+ compilerFlags =
+ map
+ Text.pack
+ [ "-Werror",
+ "-i" <> root,
+ "-odir",
+ root </> intdir,
+ "-hidir",
+ root </> intdir,
+ "--make",
+ path
+ ]
+ ++ (out /= None)
+ ?: ( map
+ Text.pack
+ [ "-main-is",
+ Namespace.toHaskellModule namespace,
+ "-o",
+ root </> outdir out
+ ],
+ []
+ ),
sysdeps =
contentLines
/> Text.unpack
@@ -359,71 +413,103 @@ analyze path = do
..
}
Namespace.Lisp -> do
+ let out =
+ contentLines
+ /> Text.unpack
+ /> Regex.match (metaOut ";;")
+ |> catMaybes
+ |> head
+ |> fromMaybe None
langdeps <- detectLispImports contentLines
Just
</ pure
Target
{ sysdeps = Set.empty,
compiler = Sbcl,
- out =
- contentLines
- /> Text.unpack
- /> Regex.match (metaOut ";;")
- |> catMaybes
- |> head,
+ compilerFlags =
+ map
+ Text.pack
+ [ "--load",
+ path,
+ "--eval",
+ "(require :asdf)",
+ "--eval",
+ "(sb-ext:save-lisp-and-die #p\"" <> (root </> outdir out) <> "\" :toplevel #'main :executable t)"
+ ],
builder = user <> "@localhost",
..
}
- Namespace.Nix ->
+ Namespace.Nix -> do
+ let builder =
+ (host == "lithium")
+ ?: ( "local",
+ Text.concat
+ [ "ssh://",
+ user,
+ "@dev.simatime.com?ssh-key=/home/",
+ user,
+ "/.ssh/id_rsa"
+ ]
+ )
Just
</ pure
Target
{ langdeps = Set.empty,
sysdeps = Set.empty,
compiler = NixBuild,
- out = Nothing,
- builder =
- if host == "lithium"
- then mempty
- else
- Text.concat
- [ "ssh://",
- user,
- "@dev.simatime.com?ssh-key=/home/",
- user,
- "/.ssh/id_rsa"
- ],
+ compilerFlags =
+ map
+ Text.pack
+ [ path,
+ "--out-link",
+ root </> nixdir </> Namespace.toPath namespace,
+ "--builders",
+ Text.unpack builder
+ ],
+ out = None,
..
}
Namespace.Scm -> do
+ let out =
+ contentLines
+ /> Text.unpack
+ /> Regex.match (metaOut ";;")
+ |> catMaybes
+ |> head
+ |> fromMaybe None
Just
</ pure
Target
{ langdeps = Set.empty,
sysdeps = Set.empty,
compiler = Guile,
- out =
- contentLines
- /> Text.unpack
- /> Regex.match (metaOut ";;")
- |> catMaybes
- |> head,
+ compilerFlags =
+ map
+ Text.pack
+ [ "compile",
+ "--r7rs",
+ "--load-path=" ++ root,
+ "--output=" ++ root </> intdir </> replaceExtension path ".scm.go",
+ path
+ ],
builder = user <> "@localhost",
..
}
Namespace.Rs -> do
+ let out =
+ contentLines
+ /> Text.unpack
+ /> Regex.match (metaOut "//")
+ |> catMaybes
+ |> head
+ |> fromMaybe None
Just
</ pure
Target
{ langdeps = Set.empty,
sysdeps = Set.empty,
compiler = Rustc,
- out =
- contentLines
- /> Text.unpack
- /> Regex.match (metaOut "//")
- |> catMaybes
- |> head,
+ compilerFlags = map Text.pack [path, "-o", root </> outdir out],
builder = user <> "@localhost",
..
}
@@ -463,10 +549,11 @@ ghcPkgFindModule acc m = do
-- | Some rules for detecting the how to compile a ghc module. If there is an
-- out, then we know it's some Exe, otherwise it's a Lib.
-detectGhcCompiler :: Maybe Out -> Compiler
+detectGhcCompiler :: Out -> Compiler
detectGhcCompiler = \case
- Just _ -> GhcExe
- Nothing -> GhcLib
+ Bin _ -> GhcExe
+ Lib _ -> GhcLib
+ None -> GhcLib
isFailure :: Exit.ExitCode -> Bool
isFailure (Exit.ExitFailure _) = True
@@ -480,11 +567,10 @@ test :: Bool -> Target -> IO Exit.ExitCode
test loud Target {..} = case compiler of
GhcExe -> do
root <- Env.getEnv "BIZ_ROOT"
- let o = Maybe.fromJust out
run
<| Proc
{ loud = loud,
- cmd = root </> outdir o,
+ cmd = root </> outdir out,
args = ["test"],
ns = namespace,
onFailure = Log.fail ["test", nschunk namespace] >> Log.br,
@@ -499,45 +585,16 @@ build :: Bool -> Bool -> Target -> IO Exit.ExitCode
build andTest loud target@Target {..} = do
root <- Env.getEnv "BIZ_ROOT"
case compiler of
- Gcc -> case out of
- Just ou -> case ou of
- Bin _ -> do
- Log.info ["bild", "bin", "gcc", nschunk namespace]
- let baseFlags = ["-o", root </> outdir ou, path]
- proc loud namespace "gcc" baseFlags
- Lib _ -> do
- Log.info ["bild", "lib", "gcc", nschunk namespace]
- let baseFlags = ["-o", root </> outdir ou, path]
- if "guile_3_0" `elem` sysdeps
- then do
- compileFlags <-
- Process.readProcess "guile-config" ["compile"] ""
- /> String.words
- compileFlags <> baseFlags <> ["-shared", "-fPIC"]
- |> proc loud namespace "gcc"
- else proc loud namespace "gcc" baseFlags
- Nothing -> Exit.die "no bin or lib found"
+ Gcc ->
+ Log.info ["bild", label, "gcc", nschunk namespace]
+ >> proc loud namespace "gcc" compilerFlags
+ where
+ label = case out of
+ Bin _ -> "bin"
+ _ -> "lib"
GhcExe -> do
Log.info ["bild", "dev", "ghc-exe", nschunk namespace]
- let o = Maybe.fromJust out
- exitcode <-
- proc
- loud
- namespace
- "ghc"
- [ "-Werror",
- "-i" <> root,
- "-odir",
- root </> intdir,
- "-hidir",
- root </> intdir,
- "--make",
- path,
- "-main-is",
- Namespace.toHaskellModule namespace,
- "-o",
- root </> outdir o
- ]
+ exitcode <- proc loud namespace "ghc" compilerFlags
if andTest && isSuccess exitcode
then test loud target
else pure exitcode
@@ -547,32 +604,13 @@ build andTest loud target@Target {..} = do
loud
namespace
"ghc"
- [ "-Werror",
- "-i" <> root,
- "-odir",
- root </> intdir,
- "-hidir",
- root </> intdir,
- "--make",
- path
- ]
+ compilerFlags
Guile -> do
Log.info ["bild", "dev", "guile", nschunk namespace]
- _ <-
- proc
- loud
- namespace
- "guild"
- [ "compile",
- "--r7rs",
- "--load-path=" ++ root,
- "--output=" ++ root </> intdir </> replaceExtension path ".scm.go",
- path
- ]
- when (isJust out) <| do
- let o = Maybe.fromJust out
+ _ <- proc loud namespace "guild" compilerFlags
+ when (out /= None) <| do
writeFile
- (root </> outdir o)
+ (root </> outdir out)
<| Text.pack
<| joinWith
"\n"
@@ -584,56 +622,21 @@ build andTest loud target@Target {..} = do
<> Namespace.toPath namespace
<> " \"$@\""
]
- p <- Dir.getPermissions <| root </> outdir o
- Dir.setPermissions (root </> outdir o) (Dir.setOwnerExecutable True p)
+ p <- Dir.getPermissions <| root </> outdir out
+ Dir.setPermissions (root </> outdir out) (Dir.setOwnerExecutable True p)
pure Exit.ExitSuccess
NixBuild -> do
- Log.info
- [ "bild",
- "nix",
- if Text.null builder
- then "local"
- else builder,
- nschunk namespace
- ]
- proc
- loud
- namespace
- "nix-build"
- [ path,
- "--out-link",
- root </> nixdir </> Namespace.toPath namespace,
- "--builders",
- Text.unpack builder
- ]
+ Log.info ["bild", "nix", builder, nschunk namespace]
+ proc loud namespace "nix-build" compilerFlags
Copy -> do
Log.warn ["bild", "copy", "TODO", nschunk namespace]
pure Exit.ExitSuccess
Rustc -> do
Log.info ["bild", "dev", "rust", nschunk namespace]
- let out' = Maybe.fromJust out
- proc
- loud
- namespace
- "rustc"
- [ path,
- "-o",
- root </> outdir out'
- ]
+ proc loud namespace "rustc" compilerFlags
Sbcl -> do
Log.info ["bild", "dev", "lisp", nschunk namespace]
- let out' = Maybe.fromJust out
- proc
- loud
- namespace
- "sbcl"
- [ "--load",
- path,
- "--eval",
- "(require :asdf)",
- "--eval",
- "(sb-ext:save-lisp-and-die #p\"" <> (root </> outdir out') <> "\" :toplevel #'main :executable t)"
- ]
+ proc loud namespace "sbcl" compilerFlags
data Proc = Proc
{ loud :: Bool,
@@ -663,14 +666,14 @@ run Proc {..} = do
else onSuccess >> pure exitcode
-- | Helper for running a standard bild subprocess.
-proc :: Bool -> Namespace -> String -> [String] -> IO Exit.ExitCode
+proc :: Bool -> Namespace -> String -> [Text] -> IO Exit.ExitCode
proc loud namespace cmd args =
run
<| Proc
{ loud = loud,
ns = namespace,
cmd = cmd,
- args = args,
+ args = map Text.unpack args,
onFailure = Log.fail ["bild", nschunk namespace] >> Log.br,
onSuccess = Log.good ["bild", nschunk namespace] >> Log.br
}