From d8fe6f7ac54f155fe5a3c33509249a70d0c816c5 Mon Sep 17 00:00:00 2001 From: Ben Sima Date: Fri, 29 Jul 2022 10:50:41 -0400 Subject: Implement Guile linking for C builds In order to write Guile code against C, I need to distiguish between libs and bins, so I did that, then I got the flags that gcc needs from `guile-config` and put them in the args for any C lib build. I tested this with Bessel.c and Bessel.scm (not in this patch, because I don't really want that code in my tree, I'll come up with another way to test it later). --- .envrc | 5 +++- Biz/Bild.hs | 83 +++++++++++++++++++++++++++++++++++++++++++++--------------- Biz/Bild.nix | 5 ++++ Biz/Ide/repl | 1 + 4 files changed, 72 insertions(+), 22 deletions(-) diff --git a/.envrc b/.envrc index cdcae62..61214db 100644 --- a/.envrc +++ b/.envrc @@ -13,9 +13,12 @@ # scripts for editing go here PATH_add $BIZ_ROOT/Biz/Ide # -# bild outputs go here +# executable bild outputs go here PATH_add $BIZ_ROOT/_/bin # +# library/linkable bild outputs go here + export LTDL_LIBRARY_PATH=$BIZ_ROOT/_/lib +# # Biz/Dragons.hs: export GITHUB_CLIENT_ID=aa575dc96263bc99556d export GITHUB_CLIENT_STATE=$(cat /proc/sys/kernel/random/uuid) diff --git a/Biz/Bild.hs b/Biz/Bild.hs index 602a326..c5777f9 100644 --- a/Biz/Bild.hs +++ b/Biz/Bild.hs @@ -198,7 +198,11 @@ exitSummary exits = type Dep = String -type Out = String +data Out = Lib String | Bin String + deriving (Show) + +instance Aeson.ToJSON Out where + toJSON out = outdir out |> Text.pack |> Aeson.String data Compiler = Copy @@ -257,8 +261,12 @@ isBuildableNs = \case ] -- | Emulate the *nix hierarchy in the cabdir. -bindir, intdir, nixdir, vardir :: String -bindir = "_/bin" +outdir :: Out -> String +outdir = \case + Bin o -> "_/bin" o + Lib o -> "_/lib" o + +intdir, nixdir, vardir :: String intdir = "_/int" nixdir = "_/nix" vardir = "_/var" @@ -267,7 +275,8 @@ createHier :: String -> IO () createHier root = traverse_ (Dir.createDirectoryIfMissing True) - [ root bindir, + [ root (outdir <| Bin ""), + root (outdir <| Lib ""), root intdir, root nixdir, root vardir @@ -360,7 +369,7 @@ analyze path = do out = contentLines /> Text.unpack - /> Regex.match (metaOut "//") + /> Regex.match (metaOut "//" <|> metaLib "//") |> catMaybes |> head, builder = user <> "@localhost", @@ -482,10 +491,11 @@ 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 bindir Maybe.fromJust out, + cmd = root outdir o, args = ["test"], ns = namespace, onFailure = Log.fail ["test", nschunk namespace] >> Log.br, @@ -500,11 +510,27 @@ build :: Bool -> Bool -> Target -> IO Exit.ExitCode build andTest loud target@Target {..} = do root <- Env.getEnv "BIZ_ROOT" case compiler of - Gcc -> do - Log.info ["bild", "dev", "gcc", nschunk namespace] - proc loud namespace "gcc" ["-o", root bindir Maybe.fromJust out, path] + 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" GhcExe -> do Log.info ["bild", "dev", "ghc-exe", nschunk namespace] + let o = Maybe.fromJust out exitcode <- proc loud @@ -521,7 +547,7 @@ build andTest loud target@Target {..} = do "-main-is", Namespace.toHaskellModule namespace, "-o", - root bindir Maybe.fromJust out + root outdir o ] if andTest && isSuccess exitcode then test loud target @@ -557,20 +583,20 @@ build andTest loud target@Target {..} = do when (isJust out) <| do let o = Maybe.fromJust out writeFile - (root bindir o) + (root outdir o) <| Text.pack <| joinWith "\n" [ "#!/usr/bin/env bash", "guile -C \"" <> root intdir - <> "\" -c \"(use-modules " - <> Namespace.toSchemeModule namespace - <> ") (main (command-line))\"" + <> "\" -e main " + <> "-s " + <> Namespace.toPath namespace <> " \"$@\"" ] - p <- Dir.getPermissions <| root bindir o - Dir.setPermissions (root bindir o) (Dir.setOwnerExecutable True p) + p <- Dir.getPermissions <| root outdir o + Dir.setPermissions (root outdir o) (Dir.setOwnerExecutable True p) pure Exit.ExitSuccess NixBuild -> do Log.info @@ -596,16 +622,18 @@ build andTest loud target@Target {..} = do pure Exit.ExitSuccess Rustc -> do Log.info ["bild", "dev", "rust", nschunk namespace] + let out' = Maybe.fromJust out proc loud namespace "rustc" [ path, "-o", - root bindir Maybe.fromJust out + root outdir out' ] Sbcl -> do Log.info ["bild", "dev", "lisp", nschunk namespace] + let out' = Maybe.fromJust out proc loud namespace @@ -615,7 +643,7 @@ build andTest loud target@Target {..} = do "--eval", "(require :asdf)", "--eval", - "(sb-ext:save-lisp-and-die #p\"" <> (root bindir Maybe.fromJust out) <> "\" :toplevel #'main :executable t)" + "(sb-ext:save-lisp-and-die #p\"" <> (root outdir out') <> "\" :toplevel #'main :executable t)" ] data Proc = Proc @@ -666,13 +694,26 @@ nschunk :: Namespace -> Text nschunk = Namespace.toPath .> Text.pack metaDep :: Regex.RE Char Dep -metaDep = Regex.string "-- : dep " *> Regex.many (Regex.psym Char.isAlpha) +metaDep = + Regex.string "-- : dep " + *> Regex.many (Regex.psym Char.isAlpha) metaSys :: [Char] -> Regex.RE Char Dep -metaSys comment = Regex.string (comment ++ " : sys ") *> Regex.many (Regex.psym (not <. Char.isSpace)) +metaSys comment = + Regex.string (comment ++ " : sys ") + *> Regex.many (Regex.psym (not <. Char.isSpace)) metaOut :: [Char] -> Regex.RE Char Out -metaOut comment = Regex.string (comment ++ " : out ") *> Regex.many (Regex.psym (/= ' ')) +metaOut comment = + Regex.string (comment ++ " : out ") + *> Regex.many (Regex.psym (/= ' ')) + /> Bin + +metaLib :: [Char] -> Regex.RE Char Out +metaLib comment = + Regex.string (comment ++ " : lib ") + *> Regex.many (Regex.psym (/= ' ')) + /> Lib haskellImports :: Regex.RE Char String haskellImports = diff --git a/Biz/Bild.nix b/Biz/Bild.nix index da0c6a8..40309a1 100644 --- a/Biz/Bild.nix +++ b/Biz/Bild.nix @@ -45,6 +45,11 @@ rec { src = ../.; nativeBuildInputs = [ private.ghcPackageSetBild ]; buildInputs = [ nixpkgs.makeWrapper ]; + propagatedBuildInputs = with nixpkgs; [ + pkg-config + guile_3_0 + sbcl + ]; strictDeps = true; buildPhase = '' mkdir -p $out/bin $out/lib/ghc-${private.ghcPackageSetFull.version} diff --git a/Biz/Ide/repl b/Biz/Ide/repl index 4c77e5b..a8fc124 100755 --- a/Biz/Ide/repl +++ b/Biz/Ide/repl @@ -32,6 +32,7 @@ fi BILD="(import $BIZ_ROOT/Biz/Bild.nix {})" for lib in ${sysdeps[@]}; do flags+=(--packages "$BILD.private.nixpkgs.${lib}") + flags+=(--packages "$BILD.private.nixpkgs.pkg-config") done case $exts in C) -- cgit v1.2.3