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 }