1 | ;;;; TODO: move to a utility package |
---|
2 | (in-package :abcl/build) |
---|
3 | |
---|
4 | ;;; TODO remove |
---|
5 | (defun localize-executable-name (name) |
---|
6 | (let* ((p (if (pathnamep name) |
---|
7 | name |
---|
8 | (pathname name))) |
---|
9 | (type (pathname-type p))) |
---|
10 | (make-pathname :defaults p |
---|
11 | :type |
---|
12 | (if (uiop:os-windows-p) |
---|
13 | (when (null type) |
---|
14 | "exe") |
---|
15 | type)))) |
---|
16 | |
---|
17 | (defun possible-executable-names (name |
---|
18 | &key (suffixes '("exe" "cmd" "bat") suffixes-p)) |
---|
19 | (let* ((p (if (pathnamep name) |
---|
20 | name |
---|
21 | (pathname name))) |
---|
22 | (type (pathname-type p))) |
---|
23 | (unless (or (uiop:os-windows-p) suffixes-p) |
---|
24 | (return-from possible-executable-names |
---|
25 | (listify name))) |
---|
26 | (loop |
---|
27 | :for suffix :in suffixes |
---|
28 | :with result = (list p) |
---|
29 | :doing (push (make-pathname :defaults p :type suffix) |
---|
30 | result) |
---|
31 | :finally (return (nreverse result))))) |
---|
32 | |
---|
33 | (defun introspect-path-for (executable) |
---|
34 | (let ((which-command (if (uiop:os-windows-p) |
---|
35 | "where" |
---|
36 | "which"))) |
---|
37 | (when (ignore-errors |
---|
38 | (uiop:run-program (list which-command which-command) :output :string)) |
---|
39 | (dolist (p (possible-executable-names executable)) |
---|
40 | (let ((raw-result |
---|
41 | (ignore-errors (uiop:run-program |
---|
42 | (list which-command |
---|
43 | (namestring p)) |
---|
44 | :output :string)))) |
---|
45 | (when raw-result |
---|
46 | (let ((result (first (split-string raw-result #\Newline)))) |
---|
47 | (return-from introspect-path-for |
---|
48 | (values |
---|
49 | result |
---|
50 | (pathname result)))))))))) |
---|
51 | |
---|
52 | (defun probe-for-executable (directory executable) |
---|
53 | (dolist (p (possible-executable-names executable)) |
---|
54 | (let ((pathname |
---|
55 | (probe-file |
---|
56 | (merge-pathnames executable directory)))) |
---|
57 | (when pathname |
---|
58 | (return-from probe-for-executable |
---|
59 | pathname))))) |
---|
60 | |
---|
61 | (defun split-string (string split-char) |
---|
62 | (loop :for i = 0 :then (1+ j) |
---|
63 | :as j = (position split-char string :test #'string-equal :start i) |
---|
64 | :collect (subseq string i j) |
---|
65 | :while j)) |
---|
66 | |
---|
67 | (defun stringify (thing) |
---|
68 | (cond |
---|
69 | ((pathnamep thing) |
---|
70 | (namestring thing)) |
---|
71 | ((stringp thing) |
---|
72 | thing) |
---|
73 | (t |
---|
74 | (error "Don't know how stringify ~a." thing)))) |
---|
75 | |
---|
76 | (defun listify (thing) |
---|
77 | (if (consp thing) |
---|
78 | thing |
---|
79 | (list thing))) |
---|
80 | |
---|
81 | (defun some-directory-containing (executable) |
---|
82 | ;; search path |
---|
83 | (let ((in-path (introspect-path-for executable))) |
---|
84 | (when in-path |
---|
85 | (return-from some-directory-containing |
---|
86 | in-path)) |
---|
87 | (dolist (d |
---|
88 | (if (uiop:os-windows-p) |
---|
89 | '(#p"c:/Program Files/") ;; TODO localize me! |
---|
90 | '(#p"/usr/local/bin/" #p"/opt/local/bin/" #p"/usr/bin/"))) |
---|
91 | (let* ((e (localize-executable-name |
---|
92 | (merge-pathnames :defaults d |
---|
93 | :name executable))) |
---|
94 | (p (probe-file p))) |
---|
95 | (when p |
---|
96 | (return-from some-directory-containing p)))))) |
---|
97 | |
---|
98 | |
---|
99 | |
---|
100 | |
---|