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