asdf.lisp - clic - Clic is an command line interactive client for gopher writte… | |
git clone git://bitreich.org/clic/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65… | |
Log | |
Files | |
Refs | |
Tags | |
README | |
LICENSE | |
--- | |
asdf.lisp (9329B) | |
--- | |
1 ;;;; -*- Mode: lisp; indent-tabs-mode: nil -*- | |
2 ;;; | |
3 ;;; asdf.lisp --- ASDF components for cffi/c2ffi. | |
4 ;;; | |
5 ;;; Copyright (C) 2015, Attila Lendvai <[email protected]> | |
6 ;;; | |
7 ;;; Permission is hereby granted, free of charge, to any person | |
8 ;;; obtaining a copy of this software and associated documentation | |
9 ;;; files (the "Software"), to deal in the Software without | |
10 ;;; restriction, including without limitation the rights to use, copy, | |
11 ;;; modify, merge, publish, distribute, sublicense, and/or sell copies | |
12 ;;; of the Software, and to permit persons to whom the Software is | |
13 ;;; furnished to do so, subject to the following conditions: | |
14 ;;; | |
15 ;;; The above copyright notice and this permission notice shall be | |
16 ;;; included in all copies or substantial portions of the Software. | |
17 ;;; | |
18 ;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
19 ;;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
20 ;;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
21 ;;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | |
22 ;;; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | |
23 ;;; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
24 ;;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
25 ;;; DEALINGS IN THE SOFTWARE. | |
26 ;;; | |
27 | |
28 (in-package #:cffi/c2ffi) | |
29 | |
30 (defclass c2ffi-file (cl-source-file) | |
31 ((package :initarg :package | |
32 :initform nil | |
33 :accessor c2ffi-file/package) | |
34 (c2ffi-executable :initarg :c2ffi-executable | |
35 :accessor c2ffi-file/c2ffi-executable) | |
36 (trace-c2ffi :initarg :trace-c2ffi | |
37 :accessor c2ffi-file/trace-c2ffi) | |
38 (prelude :initform nil | |
39 :initarg :prelude | |
40 :accessor c2ffi-file/prelude) | |
41 (sys-include-paths :initarg :sys-include-paths | |
42 :initform nil | |
43 :accessor c2ffi-file/sys-include-paths) | |
44 (exclude-archs :initarg :exclude-archs | |
45 :initform nil | |
46 :accessor c2ffi-file/exclude-archs) | |
47 ;; The following slots correspond to an arg of the same name for | |
48 ;; the generator function. No accessors are needed, they just hold | |
49 ;; the data until it gets delegated to the generator function using | |
50 ;; SLOT-VALUE and a LOOP. | |
51 (ffi-name-transformer :initarg :ffi-name-transformer | |
52 :initform 'default-ffi-name-transformer) | |
53 (ffi-name-export-predicate :initarg :ffi-name-export-predicate | |
54 :initform 'default-ffi-name-export-predica… | |
55 (ffi-type-transformer :initarg :ffi-type-transformer | |
56 :initform 'default-ffi-type-transformer) | |
57 (callback-factory :initarg :callback-factory | |
58 :initform 'default-callback-factory) | |
59 (foreign-library-name :initarg :foreign-library-name | |
60 :initform nil) | |
61 (foreign-library-spec :initarg :foreign-library-spec | |
62 :initform nil) | |
63 (emit-generated-name-mappings :initarg :emit-generated-name-mappings | |
64 :initform :t) | |
65 (include-sources :initarg :include-sources | |
66 :initform :all) | |
67 (exclude-sources :initarg :exclude-sources | |
68 :initform nil) | |
69 (include-definitions :initarg :include-definitions | |
70 :initform :all) | |
71 (exclude-definitions :initarg :exclude-definitions | |
72 :initform nil)) | |
73 (:default-initargs | |
74 :type nil) | |
75 (:documentation | |
76 "The input of this ASDF component is a C header file and the configur… | |
77 the binding generation process. This header file will define the initial… | |
78 the generation process, which can be further filtered by other configura… | |
79 parameters. | |
80 | |
81 A clang/llvm based external program called 'c2ffi' is used to process th… | |
82 file and generate a json spec file for each supported architecture tripl… | |
83 these .spec files are only (re)generated by the author of the lib and ar… | |
84 the corresponding source repository. It needs to be done manually by inv… | |
85 following command: | |
86 | |
87 (cffi/c2ffi:generate-spec :your-system) | |
88 | |
89 which is a shorthand for: | |
90 | |
91 (asdf:operate 'cffi/c2ffi::generate-spec-op :your-system) | |
92 | |
93 The generation of the underlying platform's json file must succeed, but … | |
94 generation for the other arch's is allowed to fail | |
95 \(see ENSURE-SPEC-FILE-IS-UP-TO-DATE for details). | |
96 | |
97 During the normal build process the json file is used as the input to ge… | |
98 a lisp file containing the CFFI definitions (see PROCESS-C2FFI-SPEC-FILE… | |
99 This file will be placed next to the .spec file, and will be compiled as… | |
100 other lisp file. This process requires loading the ASDF system called | |
101 \"cffi/c2ffi-generator\" that has more dependencies than CFFI itself. If… | |
102 want to avoid those extra dependencies in your project, then you can che… | |
103 these generated lisp files into your source repository, but keep in mind… | |
104 you'll need to manually force their regeneration if CFFI/C2FFI itself ge… | |
105 updated (by e.g. deleting them from the filesystem) .")) | |
106 | |
107 (defun input-file (operation component) | |
108 (let ((files (input-files operation component))) | |
109 (assert (length=n-p files 1)) | |
110 (first files))) | |
111 | |
112 (defclass generate-spec-op (downward-operation) | |
113 ()) | |
114 | |
115 (defun generate-spec (system) | |
116 (asdf:operate 'generate-spec-op system)) | |
117 | |
118 (defmethod input-files ((op generate-spec-op) (c c2ffi-file)) | |
119 (list (component-pathname c))) | |
120 | |
121 (defmethod component-depends-on ((op generate-spec-op) (c c2ffi-file)) | |
122 `((prepare-op ,c) ,@(call-next-method))) | |
123 | |
124 (defmethod output-files ((op generate-spec-op) (c c2ffi-file)) | |
125 (let* ((input-file (input-file op c)) | |
126 (spec-file (spec-path input-file))) | |
127 (values | |
128 (list spec-file) | |
129 ;; Tell ASDF not to apply output translation. | |
130 t))) | |
131 | |
132 (defmethod perform ((op generate-spec-op) (c asdf:component)) | |
133 (values)) | |
134 | |
135 (defmethod perform ((op generate-spec-op) (c c2ffi-file)) | |
136 (let ((input-file (input-file op c)) | |
137 (*c2ffi-executable* (if (slot-boundp c 'c2ffi-executable) | |
138 (c2ffi-file/c2ffi-executable c) | |
139 *c2ffi-executable*)) | |
140 (*trace-c2ffi* (if (slot-boundp c 'trace-c2ffi) | |
141 (c2ffi-file/trace-c2ffi c) | |
142 *trace-c2ffi*))) | |
143 ;; NOTE: we don't call OUTPUT-FILE here, which may be a violation | |
144 ;; of the ASDF contract, that promises that OUTPUT-FILE can be | |
145 ;; customized by users. | |
146 (ensure-spec-file-is-up-to-date | |
147 input-file | |
148 :exclude-archs (c2ffi-file/exclude-archs c) | |
149 :sys-include-paths (c2ffi-file/sys-include-paths c)))) | |
150 | |
151 (defclass generate-lisp-op (downward-operation) | |
152 ()) | |
153 | |
154 (defmethod component-depends-on ((op generate-lisp-op) (c c2ffi-file)) | |
155 `((load-op ,(find-system "cffi/c2ffi-generator")) | |
156 ,@(call-next-method))) | |
157 | |
158 (defmethod component-depends-on ((op compile-op) (c c2ffi-file)) | |
159 `((generate-lisp-op ,c) ,@(call-next-method))) | |
160 | |
161 (defmethod component-depends-on ((op load-source-op) (c c2ffi-file)) | |
162 `((generate-lisp-op ,c) ,@(call-next-method))) | |
163 | |
164 (defmethod input-files ((op generate-lisp-op) (c c2ffi-file)) | |
165 (list (output-file 'generate-spec-op c))) | |
166 | |
167 (defmethod input-files ((op compile-op) (c c2ffi-file)) | |
168 (list (output-file 'generate-lisp-op c))) | |
169 | |
170 (defmethod output-files ((op generate-lisp-op) (c c2ffi-file)) | |
171 (let* ((spec-file (input-file op c)) | |
172 (generated-lisp-file (make-pathname :type "lisp" | |
173 :defaults spec-file))) | |
174 (values | |
175 (list generated-lisp-file) | |
176 ;; Tell ASDF not to apply output translation. | |
177 t))) | |
178 | |
179 (defmethod perform ((op generate-lisp-op) (c c2ffi-file)) | |
180 (let ((spec-file (input-file op c)) | |
181 (generated-lisp-file (output-file op c))) | |
182 (with-staging-pathname (tmp-output generated-lisp-file) | |
183 (format *debug-io* "~&; CFFI/C2FFI is generating the file ~S~%" ge… | |
184 (apply 'process-c2ffi-spec-file | |
185 spec-file (c2ffi-file/package c) | |
186 :output tmp-output | |
187 :output-encoding (asdf:component-encoding c) | |
188 :prelude (let ((prelude (c2ffi-file/prelude c))) | |
189 (if (and (pathnamep prelude) | |
190 (not (absolute-pathname-p prelude))) | |
191 (merge-pathnames* prelude (component-pathnam… | |
192 prelude)) | |
193 ;; The following slots and keyword args have the same name … | |
194 ;; component and in PROCESS-C2FFI-SPEC-FILE, and this loop … | |
195 (loop | |
196 :for arg :in '(ffi-name-transformer | |
197 ffi-name-export-predicate | |
198 ffi-type-transformer | |
199 callback-factory | |
200 foreign-library-name | |
201 foreign-library-spec | |
202 emit-generated-name-mappings | |
203 include-sources | |
204 exclude-sources | |
205 include-definitions | |
206 exclude-definitions) | |
207 :append (list (make-keyword arg) | |
208 (slot-value c arg))))))) | |
209 | |
210 ;; Allow for naked :cffi/c2ffi-file in asdf definitions. | |
211 (setf (find-class 'asdf::cffi/c2ffi-file) (find-class 'c2ffi-file)) |