main.janet (13508B)
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 (if (= srcsubdir srcdir) 98 (libc/basename srcdir) 99 (do 100 (os/cd srcdir) 101 (string/join [(libc/basename srcdir) 102 (libc/basename srcsubdir)] "::")))) 103 (def pkgdir (path/join stowdir pkg)) 104 (def destdir (libc/mkdtemp "/tmp/instow.XXXXXX")) 105 106 (def env (os/environ)) 107 (merge-into env {:err :pipe 108 :out :pipe 109 "PATH" (string/join [(os/getenv "PATH") bindir] ":") 110 "PKG_CONFIG_PATH" (string/join 111 [(path/join libdir "pkgconfig") 112 (path/join syslibdir "pkgconfig")] ":") 113 "CFLAGS" (string/join 114 [(get env "CFLAGS" "") 115 (stropt "--include-directory-after" headerdir) 116 (stropt "-Wl,-rpath" libdir) 117 (stropt "-Wl,-rpath" syslibdir) 118 (string "-L" libdir) 119 (string "-L" syslibdir) 120 "-Wno-unused-command-line-argument"] " ") 121 "CXXFLAGS" (string/join 122 [(get env "CXXFLAGS" "") 123 (stropt "--include-directory-after" headerdir) 124 (stropt "-Wl,-rpath" libdir) 125 (stropt "-Wl,-rpath" syslibdir) 126 (string "-L" libdir) 127 (string "-L" syslibdir) 128 "-Wno-unused-command-line-argument"] " ") 129 "RUSTFLAGS" (string/join 130 ["-C" (string "link-args=-Wl,-rpath," libdir) 131 "-C" (string "link-args=-Wl,-rpath," syslibdir)] " ") 132 "PERL5LIB" (path/join libdir "perl5") 133 "GOPATH" destdir}) 134 135 (var ret 0) 136 (var state (if-let [st (get args 1)] (keyword st) :init)) 137 (var errormsg "Unknown") 138 (var prefix target) 139 (var builddir ".") 140 141 (if (file/file-exists? "./instow.log") (os/rm "./instow.log")) 142 143 (while (not= state :exit) 144 (let [log_file (file/open "./instow.log" :a)] 145 (file/write log_file (string/join ["STATE:" state "\n"] " ")) 146 (file/close log_file)) 147 (case state 148 :init 149 (cond 150 (file/file-exists? "configure") (set state :conf/configure) 151 (file/file-exists? "Makefile") (set state :build/make) 152 (file/file-exists? "go.mod") (set state :build/go) 153 (file/file-exists? "Cargo.toml") (set state :build/cargo) 154 (or (file/file-exists? "setup.py") 155 (file/file-exists? "pyproject.toml")) (set state :build/pip) 156 (file/file-exists? "Build.PL") (set state :build/perl) 157 (file/file-exists? "project.janet") (set state :build/jpm) 158 (utils/some? (libc/glob "*.pro")) (set state :conf/qmake) 159 (file/file-exists? "CMakeLists.txt") (set state :conf/cmake) 160 (file/file-exists? "autogen.sh") (set state :conf/autogen) 161 (file/file-exists? "configure.ac") (set state :conf/autoreconf) 162 (file/file-exists? "meson.build") (set state :conf/meson) 163 (file/file-exists? "wscript") (set state :conf/waf) 164 (file/file-exists? "package.json") (set state :conf/npm) 165 (errexit "Unable to auto-detect the build system")) 166 167 :conf/autoreconf 168 (checkrun :conf/configure :autoreconf "-vi") 169 170 :conf/autogen 171 (checkrun :conf/configure :autogen) 172 173 :conf/configure 174 (checkrun :build/make :configure (stropt "--prefix" prefix)) 175 176 :conf/waf 177 (do 178 (set builddir "build") 179 (checkrun :build/waf :waf "configure" "-o" builddir "--prefix" prefix)) 180 181 :conf/qmake 182 (do 183 (set builddir "build") 184 (set prefix "/usr/") 185 (checkrun :build/make 186 :qmake 187 (stropt "QMAKE_CXXFLAGS" (env "CXXFLAGS")) 188 (stropt "QMAKE_CFLAGS" (env "CFLAGS")) 189 (string "QMAKE_LIBDIR+=" libdir " " syslibdir) 190 (string "QMAKE_RPATHDIR+=" libdir " " syslibdir) 191 "-o" (path/join builddir "Makefile") 192 )) 193 194 :conf/meson 195 (do 196 (set builddir "build") 197 (checkrun :build/meson :meson "setup" builddir (stropt "--prefix" prefix))) 198 199 :conf/cmake 200 (do 201 (set builddir "build") 202 (checkrun :build/make :cmake "-B" builddir "-S" "." (stropt "-DCMAKE_INSTALL_PREFIX" prefix))) 203 204 :conf/npm 205 (checkrun :build/npm 206 :npm "install" 207 "--cache" (path/join builddir ".npm") 208 "--loglevel" "verbose" 209 "--include-workspace-root") 210 211 :build/make 212 (checkrun :install/make 213 :make 214 "-C" builddir 215 (string/format "-j%d" (libc/get_nprocs)) 216 ;(if-let [cc (os/getenv "CC")] [(stropt "CC" cc)] []) 217 ;(if-let[cxx (os/getenv "CXX")] [(stropt "CXX" cxx)] []) 218 "--" 219 ;(if-let [m (os/getenv "MAKETARGETS")] (string/split " " m) [])) 220 221 :build/go 222 (checkrun :install/go :go "build" "-v") 223 224 :build/perl 225 (checkrun :install/perl :perl "./Build.PL") 226 227 :build/waf 228 (checkrun :install/waf :waf "build" "-o" builddir) 229 230 :build/cargo 231 (do 232 (checkrun :install/cargo :cargo "build" "--locked" "--release") 233 (if (file/file-exists? "install.yml") (set state :install/rinstall))) 234 235 :build/pip 236 (do 237 (set builddir "build") 238 (checkrun :install/pip :pip "wheel" "." "-w" builddir "--no-build-isolation" "--no-deps")) 239 240 241 :build/meson 242 (checkrun :install/meson :meson "compile" "-C" builddir) 243 244 :build/npm 245 (checkrun :install/npm 246 :npm "run" "build" 247 "--cache" (path/join builddir ".npm") 248 "--loglevel" "verbose" 249 "--include-workspace-root") 250 251 :build/jpm 252 (checkrun :install/jpm :jpm "build") 253 254 :install/make 255 (checkrun :post/detectprefix 256 :make 257 "-C" builddir 258 "install" 259 ;(if-let [mf (env "MAKEFLAGS")] (string/split " " mf) []) 260 (stropt "PREFIX" prefix) 261 (stropt "prefix" prefix) 262 (stropt "CMAKE_INSTALL_PREFIX" prefix) 263 (stropt "DESTDIR" destdir) 264 (stropt "INSTALL_ROOT" destdir)) 265 266 :install/meson 267 (checkrun :move :meson "install" "-C" builddir (stropt "--destdir" destdir)) 268 269 :install/waf 270 (checkrun :move :waf "install" "-o" builddir "--destdir" destdir) 271 272 :install/perl 273 (checkrun :move :perl "./Build" "install" "--install_base" prefix "--destdir" destdir) 274 275 :install/go 276 (do 277 (set prefix "") 278 (checkrun :install/go :go "install" "-v") 279 (checkrun :move :go "clean" "-modcache")) 280 281 :install/npm 282 (do 283 (set prefix "") 284 (checkrun :move :npm "install" 285 "-g" 286 "--install-links" 287 "--cache" (path/join builddir ".npm") 288 "--prefix" destdir)) 289 290 :install/jpm 291 (checkrun :move 292 :jpm 293 (stropt "--dest-dir" destdir) 294 (stropt "--binpath" bindir) 295 (stropt "--manpath" (path/join mandir "man1")) 296 (stropt "--modpath" (path/join libdir "janet")) 297 (stropt "--libpath" libdir) 298 (stropt "--headerpath" (path/join headerdir "janet")) 299 "install") 300 301 :install/rinstall 302 (checkrun :move :rinstall "install" "-y" "--destdir" destdir "--packaging" "--prefix" prefix) 303 304 :install/cargo 305 (do 306 (set prefix "") 307 (checkrun :move :cargo "install" "--offline" "--frozen" "--no-track" "--root" destdir "--path" srcsubdir)) 308 309 :install/pip 310 (utils/letsome wheels (libc/glob (path/join builddir "*.whl")) 311 (checkrun :post/detectprefix 312 :pip "install" 313 (stropt "--root" destdir) 314 (stropt "--prefix" prefix) 315 "--no-build-isolation" 316 "--no-deps" 317 "--force-reinstall" 318 ;wheels) 319 (errexit "No wheels present")) 320 321 :post/detectprefix 322 (do 323 (if (file/dir-exists? (path/join destdir prefix "local")) (set prefix (path/join prefix "local"))) 324 (set state :move)) 325 326 :move 327 (let [log_file (file/open "./instow.log" :a) 328 installdir (path/join destdir prefix)] 329 (if (file/dir-exists? installdir) 330 (do 331 (if (file/dir-exists? pkgdir) 332 (do 333 (checkrun :stow :stow "-v" "-d" stowdir "-t" target "-D" pkg) 334 (file/rmrf pkgdir))) 335 (set state (if (nil? (libc/glob (path/join installdir "lib" "*.so.*"))) :stow :ldconfig)) 336 (if (not= state :error) 337 (nftw/nftw installdir 338 (fn [file stat ftype info] 339 (if (or (= ftype :f) (= ftype :sl)) 340 (do 341 (def dst (path/join pkgdir (string/slice file (length installdir)))) 342 (message state (string/format "MV: %s => %s" file dst) log_file) 343 (file/move-file file dst))) 0) 1024 :phys))) 344 (errexit "The destination directory doesn't contain the prefix")) 345 (file/close log_file)) 346 347 :ldconfig 348 (checkrun :stow :ldconfig "-vNn" (path/join pkgdir "lib")) 349 350 :stow 351 (checkrun :done :stow "-v" "-d" stowdir "-t" target pkg) 352 353 :error 354 (do 355 (set ret 1) 356 (printf "\x1b[2K{%s}⸉!⸊→%s" state errormsg) 357 (set state :cleanup)) 358 359 :done 360 (do 361 (printf "\x1b[2K{%s}⸉x⸊→Success" state) 362 (set state :cleanup)) 363 364 :cleanup 365 (do 366 (file/rmrf (string/join [destdir])) 367 (set state :exit)) 368 369 #default 370 (errexit (string "Unknown state: " state)))) 371 ret 372 )