asdf.lisp - clic - Clic is an command line interactive client for gopher written in Common LISP (HTM) git clone git://bitreich.org/clic/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/clic/ (DIR) Log (DIR) Files (DIR) Refs (DIR) Tags (DIR) README (DIR) 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 <attila@lendvai.name> 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-predicate) 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 configuration for 77 the binding generation process. This header file will define the initial scope of 78 the generation process, which can be further filtered by other configuration 79 parameters. 80 81 A clang/llvm based external program called 'c2ffi' is used to process this header 82 file and generate a json spec file for each supported architecture triplet. Normally 83 these .spec files are only (re)generated by the author of the lib and are checked into 84 the corresponding source repository. It needs to be done manually by invoking the 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 the 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 generate 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 any 100 other lisp file. This process requires loading the ASDF system called 101 \"cffi/c2ffi-generator\" that has more dependencies than CFFI itself. If you 102 want to avoid those extra dependencies in your project, then you can check in 103 these generated lisp files into your source repository, but keep in mind that 104 you'll need to manually force their regeneration if CFFI/C2FFI itself gets 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~%" generated-lisp-file) 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-pathname c)) 192 prelude)) 193 ;; The following slots and keyword args have the same name in the ASDF 194 ;; component and in PROCESS-C2FFI-SPEC-FILE, and this loop copies them. 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))