main.janet (13146B)
1 (import ./libc) 2 (import ./file) 3 (import ./tools) 4 (import ./utils) 5 (import ./native/nftw) 6 7 (def columns ((libc/ioctl 1 :TIOCGWINSZ) 1)) 8 (def tty? (= (libc/isatty 1) 1)) 9 10 (def spinner "⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏") 11 (var spin (string/slice spinner 0 3)) 12 13 (defn rotate [spin_] 14 (utils/rotate spin_ spinner 3)) 15 16 (defn message [state line log_file] 17 (file/write log_file line "\n") 18 (if tty? 19 (do 20 (def pre (string/format "\x1b[2K{%s}⸉%s⸊→" state spin)) 21 (prinf "%s%s\r" pre (string/slice line 0 (max 0 (min (- columns (length pre)) (length line))))) 22 (flush)) 23 (printf "{%s}→%s" state line))) 24 25 (defn prinfer [state log_file pipe] 26 (def buf @"") 27 (while (ev/read pipe 1024 buf) 28 (def lines (string/split "\n" buf)) 29 (def len (length lines)) 30 (if (> len 1) 31 (loop [[idx line] :pairs lines] 32 (if (< idx (- len 1)) 33 (message state line log_file) 34 (do 35 (buffer/clear buf) 36 (buffer/push-string buf line))))))) 37 38 (defmacro errexit [msg] 39 ~(do 40 (set errormsg ,msg) 41 (set state :error))) 42 43 (defn procout [& args] 44 (def proc (os/spawn args :px {:out :pipe})) 45 (def buf @"") 46 (ev/gather 47 (ev/read (proc :out) :all buf) 48 (os/proc-wait proc)) 49 (os/proc-close proc) 50 buf) 51 52 (defn runp [state env & args] 53 (def log_file (file/open "./instow.log" :a)) 54 (file/write log_file (string "RUN: '" (string/join args "' '") "'\n")) 55 (def proc (os/spawn args :e env)) 56 (ev/gather 57 (prinfer state log_file (proc :out)) 58 (prinfer state log_file (proc :err)) 59 (os/proc-wait proc) 60 (while (and tty? (nil? (get proc :return-code))) 61 (ev/sleep 0.2) 62 (set spin (rotate spin)) 63 (prinf "{%s}⸉%s⸊\r" state spin) 64 (flush))) 65 (def code (get proc :return-code)) 66 (os/proc-close proc) 67 (file/close log_file) 68 code) 69 70 (defmacro checkrun [newstate cmd & args] 71 (with-syms [$ret $cmd] 72 ~(utils/letsome ,$cmd (tools/gettool ,cmd) 73 (let [,$ret (runp state env ,$cmd ,;args)] 74 (if (= ,$ret 0) 75 (set state ,newstate) 76 (errexit (string/format "Command '%s' failed with code: %d" ,$cmd ,$ret)))) 77 (errexit (string/format "Unable to find the tool '%s'" ,cmd))))) 78 79 (defn path/join [& args] 80 (string/join [;args] "/")) 81 82 (defn stropt [a b] 83 (string/join [a b] "=")) 84 85 (defn main [& args] 86 (def home (os/getenv "HOME")) 87 (def target (path/join home ".usr" "local")) 88 (def bindir (path/join target "bin")) 89 (def mandir (path/join target "share" "man")) 90 (def headerdir (path/join target "include")) 91 (def libdir (path/join target "lib")) 92 (def triplet (string/slice (procout "gcc" "-dumpmachine") 0 -2)) 93 (def syslibdir (path/join libdir triplet)) 94 (def stowdir (path/join target "stow")) 95 (def srcdir (string/slice (procout "git" "rev-parse" "--show-toplevel") 0 -2)) 96 (def srcsubdir (os/cwd)) 97 (def pkg (libc/basename srcdir)) 98 (def pkgdir (path/join stowdir pkg)) 99 (def destdir (libc/mkdtemp "/tmp/instow.XXXXXX")) 100 101 (def env (os/environ)) 102 (merge-into env {:err :pipe 103 :out :pipe 104 "PATH" (string/join [(os/getenv "PATH") bindir] ":") 105 "PKG_CONFIG_PATH" (string/join 106 [(path/join libdir "pkgconfig") 107 (path/join syslibdir "pkgconfig")] ":") 108 "CFLAGS" (string/join 109 [(get env "CFLAGS" "") 110 (stropt "--include-directory-after" headerdir) 111 (stropt "-Wl,-rpath" libdir) 112 (stropt "-Wl,-rpath" syslibdir) 113 (string "-L" libdir) 114 (string "-L" syslibdir) 115 "-Wno-unused-command-line-argument"] " ") 116 "CXXFLAGS" (string/join 117 [(get env "CXXFLAGS" "") 118 (stropt "--include-directory-after" headerdir) 119 (stropt "-Wl,-rpath" libdir) 120 (stropt "-Wl,-rpath" syslibdir) 121 (string "-L" libdir) 122 (string "-L" syslibdir) 123 "-Wno-unused-command-line-argument"] " ") 124 "RUSTFLAGS" (string/join 125 ["-C" (string "link-args=-Wl,-rpath," libdir) 126 "-C" (string "link-args=-Wl,-rpath," syslibdir)] " ") 127 "PERL5LIB" (path/join libdir "perl5") 128 "GOPATH" destdir}) 129 130 (var ret 0) 131 (var state (if-let [st (get args 1)] (keyword st) :init)) 132 (var errormsg "Unknown") 133 (var prefix target) 134 (var builddir ".") 135 136 (if (file/file-exists? "./instow.log") (os/rm "./instow.log")) 137 138 (while (not= state :exit) 139 (let [log_file (file/open "./instow.log" :a)] 140 (file/write log_file (string/join ["STATE:" state "\n"] " ")) 141 (file/close log_file)) 142 (case state 143 :init 144 (cond 145 (file/file-exists? "configure") (set state :conf/configure) 146 (file/file-exists? "Makefile") (set state :build/make) 147 (file/file-exists? "go.mod") (set state :build/go) 148 (file/file-exists? "Cargo.toml") (set state :build/cargo) 149 (or (file/file-exists? "setup.py") 150 (file/file-exists? "pyproject.toml")) (set state :build/pip) 151 (file/file-exists? "project.janet") (set state :build/jpm) 152 (utils/some? (libc/glob "*.pro")) (set state :conf/qmake) 153 (file/file-exists? "CMakeLists.txt") (set state :conf/cmake) 154 (file/file-exists? "autogen.sh") (set state :conf/autogen) 155 (file/file-exists? "configure.ac") (set state :conf/autoreconf) 156 (file/file-exists? "meson.build") (set state :conf/meson) 157 (file/file-exists? "wscript") (set state :conf/waf) 158 (file/file-exists? "package.json") (set state :conf/npm) 159 (errexit "Unable to auto-detect the build system")) 160 161 :conf/autoreconf 162 (checkrun :conf/configure :autoreconf "-vi") 163 164 :conf/autogen 165 (checkrun :conf/configure :autogen) 166 167 :conf/configure 168 (checkrun :build/make :configure (stropt "--prefix" prefix)) 169 170 :conf/waf 171 (do 172 (set builddir "build") 173 (checkrun :build/waf :waf "configure" "-o" builddir "--prefix" prefix)) 174 175 :conf/qmake 176 (do 177 (set builddir "build") 178 (set prefix "/usr/") 179 (checkrun :build/make 180 :qmake 181 (stropt "QMAKE_CXXFLAGS" (env "CXXFLAGS")) 182 (stropt "QMAKE_CFLAGS" (env "CFLAGS")) 183 (string "QMAKE_LIBDIR+=" libdir " " syslibdir) 184 (string "QMAKE_RPATHDIR+=" libdir " " syslibdir) 185 "-o" (path/join builddir "Makefile") 186 )) 187 188 :conf/meson 189 (do 190 (set builddir "build") 191 (checkrun :build/meson :meson "setup" builddir (stropt "--prefix" prefix))) 192 193 :conf/cmake 194 (do 195 (set builddir "build") 196 (checkrun :build/make :cmake "-B" builddir "-S" "." (stropt "-DCMAKE_INSTALL_PREFIX" prefix))) 197 198 :conf/npm 199 (checkrun :build/npm 200 :npm "install" 201 "--cache" (path/join builddir ".npm") 202 "--loglevel" "verbose" 203 "--include-workspace-root") 204 205 :build/make 206 (checkrun :install/make 207 :make 208 "-C" builddir 209 (string/format "-j%d" (libc/get_nprocs)) 210 ;(if-let [cc (os/getenv "CC")] [(stropt "CC" cc)] []) 211 ;(if-let[cxx (os/getenv "CXX")] [(stropt "CXX" cxx)] []) 212 "--" 213 ;(if-let [m (os/getenv "MAKETARGETS")] (string/split " " m) [])) 214 215 :build/go 216 (checkrun :install/go :go "build" "-v") 217 218 :build/waf 219 (checkrun :install/waf :waf "build" "-o" builddir) 220 221 :build/cargo 222 (do 223 (os/cd srcdir) 224 (checkrun :install/cargo :cargo "build" "--locked" "--release") 225 (os/cd srcsubdir) 226 (if (file/file-exists? "install.yml") (set state :install/rinstall))) 227 228 :build/pip 229 (do 230 (set builddir "build") 231 (checkrun :install/pip :pip "wheel" "." "-w" builddir "--no-build-isolation" "--no-deps")) 232 233 234 :build/meson 235 (checkrun :install/meson :meson "compile" "-C" builddir) 236 237 :build/npm 238 (checkrun :install/npm 239 :npm "run" "build" 240 "--cache" (path/join builddir ".npm") 241 "--loglevel" "verbose" 242 "--include-workspace-root") 243 244 :build/jpm 245 (checkrun :install/jpm :jpm "build") 246 247 :install/make 248 (checkrun :post/detectprefix 249 :make 250 "-C" builddir 251 "install" 252 ;(if-let [mf (env "MAKEFLAGS")] (string/split " " mf) []) 253 (stropt "PREFIX" prefix) 254 (stropt "prefix" prefix) 255 (stropt "CMAKE_INSTALL_PREFIX" prefix) 256 (stropt "DESTDIR" destdir) 257 (stropt "INSTALL_ROOT" destdir)) 258 259 :install/meson 260 (checkrun :move :meson "install" "-C" builddir (stropt "--destdir" destdir)) 261 262 :install/waf 263 (checkrun :move :waf "install" "-o" builddir "--destdir" destdir) 264 265 :install/go 266 (do 267 (set prefix "") 268 (checkrun :install/go :go "install" "-v") 269 (checkrun :move :go "clean" "-modcache")) 270 271 :install/npm 272 (do 273 (set prefix "") 274 (checkrun :move :npm "install" 275 "-g" 276 "--install-links" 277 "--cache" (path/join builddir ".npm") 278 "--prefix" destdir)) 279 280 :install/jpm 281 (checkrun :move 282 :jpm 283 (stropt "--dest-dir" destdir) 284 (stropt "--binpath" bindir) 285 (stropt "--manpath" (path/join mandir "man1")) 286 (stropt "--modpath" (path/join libdir "janet")) 287 (stropt "--libpath" libdir) 288 (stropt "--headerpath" (path/join headerdir "janet")) 289 "install") 290 :install/rinstall 291 (checkrun :move :rinstall "install" "-y" "--destdir" destdir "--packaging" "--prefix" prefix) 292 293 :install/cargo 294 (do 295 (set prefix "") 296 (os/cd srcdir) 297 (checkrun :move :cargo "install" "--offline" "--frozen" "--no-track" "--root" destdir "--path" srcsubdir) 298 (os/cd srcsubdir)) 299 300 :install/pip 301 (utils/letsome wheels (libc/glob (path/join builddir "*.whl")) 302 (checkrun :post/detectprefix 303 :pip "install" 304 (stropt "--root" destdir) 305 (stropt "--prefix" prefix) 306 "--no-build-isolation" 307 "--no-deps" 308 "--force-reinstall" 309 ;wheels) 310 (errexit "No wheels present")) 311 312 :post/detectprefix 313 (do 314 (if (file/dir-exists? (path/join destdir prefix "local")) (set prefix (path/join prefix "local"))) 315 (set state :move)) 316 317 :move 318 (let [log_file (file/open "./instow.log" :a) 319 installdir (path/join destdir prefix)] 320 (if (file/dir-exists? installdir) 321 (do 322 (if (file/dir-exists? pkgdir) 323 (do 324 (checkrun :stow :stow "-v" "-d" stowdir "-t" target "-D" pkg) 325 (file/rmrf pkgdir))) 326 (set state (if (nil? (libc/glob (path/join installdir "lib" "*.so.*"))) :stow :ldconfig)) 327 (if (not= state :error) 328 (nftw/nftw installdir 329 (fn [file stat ftype info] 330 (if (or (= ftype :f) (= ftype :sl)) 331 (do 332 (def dst (path/join pkgdir (string/slice file (length installdir)))) 333 (message state (string/format "MV: %s => %s" file dst) log_file) 334 (file/move-file file dst))) 0) 1024 :phys))) 335 (errexit "The destination directory doesn't contain the prefix")) 336 (file/close log_file)) 337 338 :ldconfig 339 (checkrun :stow :ldconfig "-vNn" (path/join pkgdir "lib")) 340 341 :stow 342 (checkrun :done :stow "-v" "-d" stowdir "-t" target pkg) 343 344 :error 345 (do 346 (set ret 1) 347 (printf "\x1b[2K{%s}⸉!⸊→%s" state errormsg) 348 (set state :cleanup)) 349 350 :done 351 (do 352 (printf "\x1b[2K{%s}⸉x⸊→Success" state) 353 (set state :cleanup)) 354 355 :cleanup 356 (do 357 (file/rmrf (string/join [destdir])) 358 (set state :exit)) 359 360 #default 361 (errexit (string "Unknown state: " state)))) 362 ret 363 )