diff options
author | Ben Sima <ben@bsima.me> | 2020-11-18 20:20:27 -0500 |
---|---|---|
committer | Ben Sima <ben@bsima.me> | 2020-11-18 20:20:27 -0500 |
commit | e223b28e6820dcd9fa5c38ba22de487ada2ca0e6 (patch) | |
tree | 66061bca039242bc55338280f767d0ff64d35ba0 /Biz/Bild.hs | |
parent | ac3d455a9c0dc0b2f4afb88b56db3d16c0508428 (diff) |
Extend bild to nix targets properly
Also had to capitalize some stuff, and move some nix files around and rename
the metadata directive from 'exe' to 'out' because that just makes more sense,
and fix some compiler errors. But now bild treats both nix and hs files as
buildable things. So that's cool.
One interesting example is Biz/Pie.{nix,hs} - I can either create a dev build of
the hs file with ghc, or I can create a fully-encapsulated nix build. Its nice
to have both options because a dev build with ghc takes half the amount of time,
and I can rely on my locally cached hi and ho files. I think this shows the
power of bild, but also can be a somewhat subtle thing.
The issue really is with the separate command calls in nix builds vs dev builds.
I figure there are a few ways to fix this:
1. Try to use bild inside the nix rules. That could be interesting, but could
also lead to some weird behavior or worm holes forming.
2. Extract the command line invocation into a separate file, some kind of
really simple template that gets pulled into both programs.
It is important to consider that in the future I might want to have bild do a
module-by-module nix build of programs, but I'm not sure how that would effect
my choice here.
Diffstat (limited to 'Biz/Bild.hs')
-rw-r--r-- | Biz/Bild.hs | 97 |
1 files changed, 57 insertions, 40 deletions
diff --git a/Biz/Bild.hs b/Biz/Bild.hs index 92054f9..169fd6f 100644 --- a/Biz/Bild.hs +++ b/Biz/Bild.hs @@ -64,7 +64,7 @@ -- -- > bild A/B.hs -- --- This will build the file at ./A/B.hs, this will translate to something like +-- This will build the file at ./A/B.hs, which translates to something like -- `ghc --make A.B`. -- -- > bild -s <target> @@ -94,16 +94,16 @@ -- -- The output executable is named with: -- --- > -- : exe my-program +-- > -- : out my-program -- -- or -- --- > -- : exe my-ap.js +-- > -- : out my-ap.js -- -- When multiple compilers are possible (e.g. ghc vs ghcjs) we chose ghcjs when --- the target exe ends in .js. +-- the target @out@ ends in .js. -- --- This method of setting metadata in the module comments works pretty well, +-- This method of setting metadata in the module comments works pretty well, -- and really only needs to be done in the entrypoint module anyway. -- -- Local module deps are included by just giving the repo root to the compiler @@ -143,14 +143,14 @@ type Namespace = String type Dep = String -type Exe = String +type Out = String data Compiler = Ghc | Ghcjs | Nix deriving (Show) data Target = Target - { -- | Output executable name - exe :: Exe, + { -- | Output name + out :: Out, -- | Fully qualified namespace partitioned by '.' namespace :: Namespace, -- | Absolute path to file @@ -170,24 +170,30 @@ analyze s = do case File.takeExtension path of ".hs" -> do content <- String.lines </ Prelude.readFile path - let exe = content /> Regex.match metaExe |> catMaybes |> head |> require "exe" - let compiler = if ".js" `List.isSuffixOf` exe then Ghcjs else Ghc - return Target { - namespace = require "namespace" - <| path - |> reps root "" - |> File.dropExtension - |> reps "/" "." - |> List.stripPrefix "." - >>= Regex.match metaNamespace, - deps = content /> Regex.match metaDep |> catMaybes, - .. - } - - ".nix" -> return Target { - namespace = s, path = path, deps = [], compiler = Nix, exe = "" - } - + let out = content /> Regex.match metaOut |> catMaybes |> head |> require "out" + let compiler = if ".js" `List.isSuffixOf` out then Ghcjs else Ghc + return + Target + { namespace = + require "namespace" + <| path + |> reps root "" + |> File.dropExtension + |> reps "/" "." + |> List.stripPrefix "." + >>= Regex.match metaNamespace, + deps = content /> Regex.match metaDep |> catMaybes, + .. + } + ".nix" -> + return + Target + { namespace = s, + path = path, + deps = [], + compiler = Nix, + out = "" + } e -> panic <| "bild does not know this extension: " <> Text.pack e build :: Target -> IO () @@ -196,8 +202,8 @@ build Target {..} = do case compiler of Ghc -> do putText <| "bild: ghc: " <> Text.pack namespace - let out = root </> "_/bild/dev/bin" - Dir.createDirectoryIfMissing True out + let devOut = root </> "_/bild/dev/bin" + Dir.createDirectoryIfMissing True devOut Process.callProcess "ghc" [ "-Werror", @@ -211,12 +217,12 @@ build Target {..} = do "-main-is", namespace, "-o", - out </> exe + devOut </> out ] Ghcjs -> do putText <| "bild: ghcjs: " <> Text.pack namespace - let out = root </> "_/bild/dev/static" - Dir.createDirectoryIfMissing True out + let devOut = root </> "_/bild/dev/static" + Dir.createDirectoryIfMissing True devOut Process.callProcess "ghcjs" [ "-Werror", @@ -230,19 +236,30 @@ build Target {..} = do "-main-is", namespace, "-o", - out </> exe + devOut </> out ] Nix -> do putText <| "bild: nix: " <> Text.pack namespace cwd <- Dir.getCurrentDirectory - let qualifiedTarget = reps root "" cwd <> namespace + let nixOut = root </> "_/bild/nix" + Dir.createDirectoryIfMissing True nixOut + let qualifiedTarget = reps root "" cwd </> namespace Process.callProcess "nix-build" - [ "-o", - root </> "_/bild/nix" </> qualifiedTarget, - root </> "default.nix", - "--attr", - qualifiedTarget + [ path, + "-o", + nixOut </> qualifiedTarget, + "--arg", + "bild", + "import " <> root + </> "Biz/Bild/Rules.nix" + <> " { nixpkgs = import " + <> root + </> "Biz/Bild/Nixpkgs.nix" + <> "; }", + "--arg", + "lib", + "(import " <> root </> "Biz/Bild/Nixpkgs.nix).lib" ] metaNamespace :: Regex.RE Char Namespace @@ -253,8 +270,8 @@ metaNamespace = name <> Regex.many (Regex.sym '.') <> name metaDep :: Regex.RE Char Dep metaDep = Regex.string "-- : dep " *> Regex.many (Regex.psym Char.isAlpha) -metaExe :: Regex.RE Char Exe -metaExe = Regex.string "-- : exe " *> Regex.many (Regex.psym (/= ' ')) +metaOut :: Regex.RE Char Out +metaOut = Regex.string "-- : out " *> Regex.many (Regex.psym (/= ' ')) require :: Text -> Maybe a -> a require _ (Just x) = x |