/ dhall / Build.dhall
Build.dhall
  1  -- dhall/Build.dhall
  2  --
  3  -- Target -> BuildScript
  4  --
  5  -- Generates shell scripts that compile targets.
  6  
  7  let T = ./Target.dhall
  8  let P = ./Platform.dhall
  9  
 10  let Prelude = https://prelude.dhall-lang.org/v23.0.0/package.dhall
 11  
 12  let map = Prelude.List.map
 13  let filter = Prelude.List.filter
 14  let length = Prelude.List.length
 15  let isZero = Prelude.Natural.isZero
 16  let concatSep = Prelude.Text.concatSep
 17  
 18  -- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 19  -- Build script output
 20  -- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 21  
 22  let BuildScript = { script : Text }
 23  
 24  -- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 25  -- Helpers
 26  -- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 27  
 28  let pathToText : T.Path -> Text = \(p : T.Path) -> p._path
 29  let nameToText : T.Name -> Text = \(n : T.Name) -> n._name
 30  
 31  let spaceSep : List Text -> Text = concatSep " "
 32  
 33  let cxxStdFlag : T.CxxStd -> Text = \(s : T.CxxStd) ->
 34      merge
 35          { C23 = "-std=c23"
 36          , Cxx17 = "-std=c++17"
 37          , Cxx20 = "-std=c++20"
 38          , Cxx23 = "-std=c++23"
 39          }
 40          s
 41  
 42  let smArchFlag : T.SmArch -> Text = \(a : T.SmArch) ->
 43      merge
 44          { SM_100 = "--cuda-gpu-arch=sm_100"
 45          , SM_120 = "--cuda-gpu-arch=sm_120"
 46          }
 47          a
 48  
 49  let rustEditionFlag : T.RustEdition -> Text = \(e : T.RustEdition) ->
 50      merge
 51          { E2015 = "--edition=2015"
 52          , E2018 = "--edition=2018"
 53          , E2021 = "--edition=2021"
 54          , E2024 = "--edition=2024"
 55          }
 56          e
 57  
 58  -- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 59  -- C++ build
 60  -- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 61  
 62  let buildCxx
 63      : T.Name -> List T.Path -> T.CxxOpts -> List T.Dep -> P.CxxToolchain -> BuildScript
 64      = \(name : T.Name) ->
 65        \(srcs : List T.Path) ->
 66        \(opts : T.CxxOpts) ->
 67        \(deps : List T.Dep) ->
 68        \(tc : P.CxxToolchain) ->
 69          let srcFiles = spaceSep (map T.Path Text pathToText srcs)
 70          let std = cxxStdFlag opts.std
 71          let cflags = spaceSep opts.cflags
 72          let ldflags = spaceSep opts.ldflags
 73          let outName = nameToText name
 74  
 75          -- Nix deps handling
 76          let nixRefs = spaceSep (map T.Dep Text
 77              (\(d : T.Dep) -> merge
 78                  { Local = \(_ : T.Label) -> ""
 79                  , Nix = \(f : T.FlakeRef) -> "${f.flake}#${f.attr}"
 80                  }
 81                  d)
 82              deps)
 83  
 84          let hasNixDeps = isZero (length T.Dep
 85              (filter T.Dep
 86                  (\(d : T.Dep) -> merge { Local = \(_ : T.Label) -> False, Nix = \(_ : T.FlakeRef) -> True } d)
 87                  deps))
 88  
 89          let nixResolve = if hasNixDeps then "" else "NIX_FLAGS=$(\"$ANALYZER\" resolve ${nixRefs})"
 90  
 91          in { script =
 92  ''
 93  #!/bin/bash
 94  set -e
 95  
 96  ${nixResolve}
 97  
 98  ${pathToText tc.clangxx} \
 99      ${std} \
100      -resource-dir ${pathToText tc.resourceDir} \
101      -isystem ${pathToText tc.gccInclude} \
102      -isystem ${pathToText tc.gccIncludeArch} \
103      -isystem ${pathToText tc.glibcInclude} \
104      ${cflags} \
105      $NIX_FLAGS \
106      ${srcFiles} \
107      -o "$OUT" \
108      -B ${pathToText tc.gccLib} -L ${pathToText tc.gccLib} \
109      -L ${pathToText tc.gccLibBase} \
110      -B ${pathToText tc.glibcLib} -L ${pathToText tc.glibcLib} \
111      ${ldflags}
112  ''
113          }
114  
115  -- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
116  -- NV build (CUDA via clang)
117  -- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
118  
119  let buildNv
120      : T.Name -> List T.Path -> T.NvOpts -> List T.Dep -> P.NvToolchain -> BuildScript
121      = \(name : T.Name) ->
122        \(srcs : List T.Path) ->
123        \(opts : T.NvOpts) ->
124        \(deps : List T.Dep) ->
125        \(tc : P.NvToolchain) ->
126          let srcFiles = spaceSep (map T.Path Text pathToText srcs)
127          let std = cxxStdFlag opts.cxxOpts.std
128          let arch = smArchFlag opts.arch
129          let cflags = spaceSep opts.cxxOpts.cflags
130          let outName = nameToText name
131          let cxxTc = tc.cxx
132  
133          in { script =
134  ''
135  #!/bin/bash
136  set -e
137  
138  ${pathToText cxxTc.clangxx} \
139      -x cuda \
140      ${arch} \
141      ${std} \
142      -resource-dir ${pathToText cxxTc.resourceDir} \
143      -isystem ${pathToText tc.nvidiaSdkInclude} \
144      -isystem ${pathToText cxxTc.gccInclude} \
145      -isystem ${pathToText cxxTc.gccIncludeArch} \
146      -isystem ${pathToText cxxTc.glibcInclude} \
147      ${cflags} \
148      ${srcFiles} \
149      -o "$OUT" \
150      -L ${pathToText tc.nvidiaSdkLib} \
151      -lcudart \
152      -B ${pathToText cxxTc.gccLib} -L ${pathToText cxxTc.gccLib} \
153      -L ${pathToText cxxTc.gccLibBase} \
154      -B ${pathToText cxxTc.glibcLib} -L ${pathToText cxxTc.glibcLib}
155  ''
156          }
157  
158  -- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
159  -- Haskell build
160  -- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
161  
162  let buildHaskell
163      : T.Name -> List T.Path -> T.HaskellOpts -> List T.Dep -> P.HaskellToolchain -> BuildScript
164      = \(name : T.Name) ->
165        \(srcs : List T.Path) ->
166        \(opts : T.HaskellOpts) ->
167        \(deps : List T.Dep) ->
168        \(tc : P.HaskellToolchain) ->
169          let srcFiles = spaceSep (map T.Path Text pathToText srcs)
170          let outName = nameToText name
171          let pkgFlags = spaceSep (map Text Text (\(p : Text) -> "-package ${p}") opts.packages)
172          let ghcOpts = spaceSep opts.ghcOptions
173          let includePaths = spaceSep (map T.Path Text (\(p : T.Path) -> "-i${pathToText p}") opts.includePaths)
174  
175          in { script =
176  ''
177  #!/bin/bash
178  set -e
179  
180  ${pathToText tc.ghc} \
181      -O2 \
182      ${ghcOpts} \
183      ${pkgFlags} \
184      ${includePaths} \
185      ${srcFiles} \
186      -o "$OUT"
187  ''
188          }
189  
190  -- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
191  -- Rust build
192  -- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
193  
194  let buildRust
195      : T.Name -> List T.Path -> T.RustOpts -> List T.Dep -> P.RustToolchain -> BuildScript
196      = \(name : T.Name) ->
197        \(srcs : List T.Path) ->
198        \(opts : T.RustOpts) ->
199        \(deps : List T.Dep) ->
200        \(tc : P.RustToolchain) ->
201          let srcFiles = spaceSep (map T.Path Text pathToText srcs)
202          let outName = nameToText name
203          let edition = rustEditionFlag opts.edition
204  
205          in { script =
206  ''
207  #!/bin/bash
208  set -e
209  
210  ${pathToText tc.rustc} \
211      ${edition} \
212      -O \
213      ${srcFiles} \
214      -o "$OUT"
215  ''
216          }
217  
218  -- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
219  -- Lean build
220  -- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
221  
222  let buildLean
223      : T.Name -> List T.Path -> T.LeanOpts -> List T.Dep -> P.LeanToolchain -> BuildScript
224      = \(name : T.Name) ->
225        \(srcs : List T.Path) ->
226        \(opts : T.LeanOpts) ->
227        \(deps : List T.Dep) ->
228        \(tc : P.LeanToolchain) ->
229          let srcFiles = spaceSep (map T.Path Text pathToText srcs)
230          let outName = nameToText name
231  
232          in { script =
233  ''
234  #!/bin/bash
235  set -e
236  
237  ${pathToText tc.lean} \
238      ${srcFiles} \
239      -o "$OUT"
240  ''
241          }
242  
243  in  { BuildScript
244      , buildCxx
245      , buildNv
246      , buildHaskell
247      , buildRust
248      , buildLean
249      }