4539aedf |
1 | (defparameter *pkg-config* "pkg-config") |
300d704e |
2 | |
4539aedf |
3 | (defun split-string (string &key (start 0) (end (length string))) |
300d704e |
4 | (let ((position (position #\sp string :start start :end end))) |
4539aedf |
5 | (cond |
6 | ((zerop (- end start)) nil) |
7 | ((not position) (list (subseq string start end))) |
8 | ((= position start) (split-string string :start (1+ start) :end end)) |
9 | (t (cons |
300d704e |
10 | (subseq string start position) |
4539aedf |
11 | (split-string string :start (1+ position) :end end)))))) |
300d704e |
12 | |
4539aedf |
13 | |
14 | (defun read-lines (&optional (stream *standard-input*)) |
15 | (let ((line (read-line stream nil))) |
16 | (when line |
17 | (cons line (read-lines stream))))) |
18 | |
19 | |
20 | (defun read-string (&optional (stream *standard-input*) |
21 | (delimiter #\newline) (eof-error-p t) eof-value) |
22 | (let ((string (make-array 0 :element-type 'character |
23 | :fill-pointer t :adjustable t))) |
24 | ;; I really need to learn how to use the loop facility |
25 | (labels ((read-chars () |
26 | (let ((char (read-char stream (and eof-error-p delimiter)))) |
27 | (when char |
28 | (vector-push-extend char string) |
29 | (unless (eq char delimiter) |
30 | (read-chars)))))) |
31 | (read-chars)) |
32 | (cond |
33 | ((not (zerop (length string))) string) |
34 | ((not eof-error-p) eof-value) |
35 | ((error 'end-of-file :stream stream))))) |
36 | |
37 | |
38 | (defun run-pkg-config (package error &rest options) |
560af5c5 |
39 | (let ((process |
40 | (run-program |
300d704e |
41 | *pkg-config* (cons package options) :wait t :output :stream))) |
560af5c5 |
42 | (unless process |
300d704e |
43 | (error "Unable to run ~A" *pkg-config*)) |
4539aedf |
44 | (let ((exit-code (process-exit-code process))) |
45 | (unless (or (not error) (zerop exit-code)) |
46 | (error |
47 | (or |
48 | (read-string (process-error process) nil) |
49 | (format nil "~A terminated with exit code ~A" |
50 | *pkg-config* exit-code)))) |
51 | (let ((output (read-lines (process-output process)))) |
52 | (process-close process) |
53 | (values output exit-code))))) |
300d704e |
54 | |
55 | |
56 | (defun pkg-cflags (package) |
4539aedf |
57 | (split-string (first (run-pkg-config package t "--cflags")))) |
58 | |
59 | |
60 | (defun pkg-exists-p (package &key version atleast-version max-version |
61 | ( error t)) |
62 | (let ((version-check |
63 | (cond |
64 | (version (format nil "= ~A" version)) |
65 | (atleast-version (format nil ">= ~A" atleast-version)) |
66 | (max-version (format nil "<= ~A" max-version)) |
67 | (t "")))) |
68 | (if error |
69 | (progn |
70 | (run-pkg-config package t "--print-errors" "--exists" version-check) |
71 | t) |
72 | (multiple-value-bind (output exit-code) |
73 | (run-pkg-config package nil "--exists" version-check) |
74 | (declare (ignore output)) |
75 | (zerop exit-code))))) |
76 | |
77 | |
78 | (defun pkg-version (package) |
79 | (first (run-pkg-config package t "--modversion"))) |
80 | |
81 | |
82 | (defun pkg-variable (package variable) |
83 | (first (run-pkg-config package t "--variable" variable))) |