123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566 |
- ;;;; -------------------------------------------------------------------------
- ;;;; ASDF-Bundle
- (uiop/package:define-package :asdf/bundle
- (:recycle :asdf/bundle :asdf)
- (:use :uiop/common-lisp :uiop :asdf/upgrade
- :asdf/component :asdf/system :asdf/find-system :asdf/find-component :asdf/operation
- :asdf/action :asdf/lisp-action :asdf/plan :asdf/operate :asdf/defsystem)
- (:export
- #:bundle-op #:bundle-type #:program-system
- #:bundle-system #:bundle-pathname-type #:direct-dependency-files
- #:monolithic-op #:monolithic-bundle-op #:operation-monolithic-p
- #:basic-compile-bundle-op #:prepare-bundle-op
- #:compile-bundle-op #:load-bundle-op #:monolithic-compile-bundle-op #:monolithic-load-bundle-op
- #:lib-op #:monolithic-lib-op
- #:dll-op #:monolithic-dll-op
- #:deliver-asd-op #:monolithic-deliver-asd-op
- #:program-op #:image-op #:compiled-file #:precompiled-system #:prebuilt-system
- #:user-system-p #:user-system #:trivial-system-p
- #:prologue-code #:epilogue-code #:static-library))
- (in-package :asdf/bundle)
- (with-upgradability ()
- (defclass bundle-op (basic-compile-op)
- ;; NB: use of instance-allocated slots for operations is DEPRECATED
- ;; and only supported in a temporary fashion for backward compatibility.
- ;; Supported replacement: Define slots on program-system instead.
- ((bundle-type :initform :no-output-file :reader bundle-type :allocation :class))
- (:documentation "base class for operations that bundle outputs from multiple components"))
- (defclass monolithic-op (operation) ()
- (:documentation "A MONOLITHIC operation operates on a system *and all of its
- dependencies*. So, for example, a monolithic concatenate operation will
- concatenate together a system's components and all of its dependencies, but a
- simple concatenate operation will concatenate only the components of the system
- itself."))
- (defclass monolithic-bundle-op (bundle-op monolithic-op)
- ;; Old style way of specifying prologue and epilogue on ECL: in the monolithic operation.
- ;; DEPRECATED. Supported replacement: Define slots on program-system instead.
- ((prologue-code :initform nil :accessor prologue-code)
- (epilogue-code :initform nil :accessor epilogue-code))
- (:documentation "operations that are both monolithic-op and bundle-op"))
- (defclass program-system (system)
- ;; New style (ASDF3.1) way of specifying prologue and epilogue on ECL: in the system
- ((prologue-code :initform nil :initarg :prologue-code :reader prologue-code)
- (epilogue-code :initform nil :initarg :epilogue-code :reader epilogue-code)
- (no-uiop :initform nil :initarg :no-uiop :reader no-uiop)
- (prefix-lisp-object-files :initarg :prefix-lisp-object-files
- :initform nil :accessor prefix-lisp-object-files)
- (postfix-lisp-object-files :initarg :postfix-lisp-object-files
- :initform nil :accessor postfix-lisp-object-files)
- (extra-object-files :initarg :extra-object-files
- :initform nil :accessor extra-object-files)
- (extra-build-args :initarg :extra-build-args
- :initform nil :accessor extra-build-args)))
- (defmethod prologue-code ((x system)) nil)
- (defmethod epilogue-code ((x system)) nil)
- (defmethod no-uiop ((x system)) nil)
- (defmethod prefix-lisp-object-files ((x system)) nil)
- (defmethod postfix-lisp-object-files ((x system)) nil)
- (defmethod extra-object-files ((x system)) nil)
- (defmethod extra-build-args ((x system)) nil)
- (defclass link-op (bundle-op) ()
- (:documentation "Abstract operation for linking files together"))
- (defclass gather-operation (bundle-op)
- ((gather-operation :initform nil :allocation :class :reader gather-operation)
- (gather-type :initform :no-output-file :allocation :class :reader gather-type))
- (:documentation "Abstract operation for gathering many input files from a system"))
- (defun operation-monolithic-p (op)
- (typep op 'monolithic-op))
- ;; Dependencies of a gather-op are the actions of the dependent operation
- ;; for all the (sorted) required components for loading the system.
- ;; Monolithic operations typically use lib-op as the dependent operation,
- ;; and all system-level dependencies as required components.
- ;; Non-monolithic operations typically use compile-op as the dependent operation,
- ;; and all transitive sub-components as required components (excluding other systems).
- (defmethod component-depends-on ((o gather-operation) (s system))
- (let* ((mono (operation-monolithic-p o))
- (go (make-operation (or (gather-operation o) 'compile-op)))
- (bundle-p (typep go 'bundle-op))
- ;; In a non-mono operation, don't recurse to other systems.
- ;; In a mono operation gathering bundles, don't recurse inside systems.
- (component-type (if mono (if bundle-p 'system t) '(not system)))
- ;; In the end, only keep system bundles or non-system bundles, depending.
- (keep-component (if bundle-p 'system '(not system)))
- (deps
- ;; Required-components only looks at the dependencies of an action, excluding the action
- ;; itself, so it may be safely used by an action recursing on its dependencies (which
- ;; may or may not be an overdesigned API, since in practice we never use it that way).
- ;; Therefore, if we use :goal-operation 'load-op :keep-operation 'load-op, which looks
- ;; cleaner, we will miss the load-op on the requested system itself, which doesn't
- ;; matter for a regular system, but matters, a lot, for a package-inferred-system.
- ;; Using load-op as the goal operation and basic-compile-op as the keep-operation works
- ;; for our needs of gathering all the files we want to include in a bundle.
- ;; Note that we use basic-compile-op rather than compile-op so it will still work on
- ;; systems when *load-system-operation* is load-bundle-op.
- (required-components
- s :other-systems mono :component-type component-type :keep-component keep-component
- :goal-operation 'load-op :keep-operation 'basic-compile-op)))
- `((,go ,@deps) ,@(call-next-method))))
- ;; Create a single fasl for the entire library
- (defclass basic-compile-bundle-op (bundle-op)
- ((gather-type :initform #-(or clasp ecl mkcl) :fasl #+(or clasp ecl mkcl) :object
- :allocation :class)
- (bundle-type :initform :fasl :allocation :class))
- (:documentation "Base class for compiling into a bundle"))
- ;; Analog to prepare-op, for load-bundle-op and compile-bundle-op
- (defclass prepare-bundle-op (sideway-operation)
- ((sideway-operation
- :initform #+(or clasp ecl mkcl) 'load-bundle-op #-(or clasp ecl mkcl) 'load-op
- :allocation :class))
- (:documentation "Operation class for loading the bundles of a system's dependencies"))
- (defclass lib-op (link-op gather-operation non-propagating-operation)
- ((gather-type :initform :object :allocation :class)
- (bundle-type :initform :lib :allocation :class))
- (:documentation "Compile the system and produce a linkable static library (.a/.lib)
- for all the linkable object files associated with the system. Compare with DLL-OP.
- On most implementations, these object files only include extensions to the runtime
- written in C or another language with a compiler producing linkable object files.
- On CLASP, ECL, MKCL, these object files _also_ include the contents of Lisp files
- themselves. In any case, this operation will produce what you need to further build
- a static runtime for your system, or a dynamic library to load in an existing runtime."))
- ;; What works: on ECL, CLASP(?), MKCL, we link the many .o files from the system into the .so;
- ;; on other implementations, we combine (usually concatenate) the .fasl files into one.
- (defclass compile-bundle-op (basic-compile-bundle-op selfward-operation gather-operation
- #+(or clasp ecl mkcl) link-op)
- ((selfward-operation :initform '(prepare-bundle-op) :allocation :class))
- (:documentation "This operator is an alternative to COMPILE-OP. Build a system
- and all of its dependencies, but build only a single (\"monolithic\") FASL, instead
- of one per source file, which may be more resource efficient. That monolithic
- FASL should be loaded with LOAD-BUNDLE-OP, rather than LOAD-OP."))
- (defclass load-bundle-op (basic-load-op selfward-operation)
- ((selfward-operation :initform '(prepare-bundle-op compile-bundle-op) :allocation :class))
- (:documentation "This operator is an alternative to LOAD-OP. Build a system
- and all of its dependencies, using COMPILE-BUNDLE-OP. The difference with
- respect to LOAD-OP is that it builds only a single FASL, which may be
- faster and more resource efficient."))
- ;; NB: since the monolithic-op's can't be sideway-operation's,
- ;; if we wanted lib-op, dll-op, deliver-asd-op to be sideway-operation's,
- ;; we'd have to have the monolithic-op not inherit from the main op,
- ;; but instead inherit from a basic-FOO-op as with basic-compile-bundle-op above.
- (defclass dll-op (link-op gather-operation non-propagating-operation)
- ((gather-type :initform :object :allocation :class)
- (bundle-type :initform :dll :allocation :class))
- (:documentation "Compile the system and produce a dynamic loadable library (.so/.dll)
- for all the linkable object files associated with the system. Compare with LIB-OP."))
- (defclass deliver-asd-op (basic-compile-op selfward-operation)
- ((selfward-operation
- ;; TODO: implement link-op on all implementations, and make that
- ;; '(compile-bundle-op lib-op #-(or clasp ecl mkcl) dll-op)
- :initform '(compile-bundle-op #+(or clasp ecl mkcl) lib-op)
- :allocation :class))
- (:documentation "produce an asd file for delivering the system as a single fasl"))
- (defclass monolithic-deliver-asd-op (deliver-asd-op monolithic-bundle-op)
- ((selfward-operation
- ;; TODO: implement link-op on all implementations, and make that
- ;; '(monolithic-compile-bundle-op monolithic-lib-op #-(or clasp ecl mkcl) monolithic-dll-op)
- :initform '(monolithic-compile-bundle-op #+(or clasp ecl mkcl) monolithic-lib-op)
- :allocation :class))
- (:documentation "produce fasl and asd files for combined system and dependencies."))
- (defclass monolithic-compile-bundle-op
- (basic-compile-bundle-op monolithic-bundle-op
- #+(or clasp ecl mkcl) link-op gather-operation non-propagating-operation)
- ()
- (:documentation "Create a single fasl for the system and its dependencies."))
- (defclass monolithic-load-bundle-op (load-bundle-op monolithic-bundle-op)
- ((selfward-operation :initform 'monolithic-compile-bundle-op :allocation :class))
- (:documentation "Load a single fasl for the system and its dependencies."))
- (defclass monolithic-lib-op (lib-op monolithic-bundle-op non-propagating-operation)
- ((gather-type :initform :object :allocation :class))
- (:documentation "Compile the system and produce a linkable static library (.a/.lib)
- for all the linkable object files associated with the system or its dependencies. See LIB-OP."))
- (defclass monolithic-dll-op (dll-op monolithic-bundle-op non-propagating-operation)
- ((gather-type :initform :object :allocation :class))
- (:documentation "Compile the system and produce a dynamic loadable library (.so/.dll)
- for all the linkable object files associated with the system or its dependencies. See LIB-OP"))
- (defclass image-op (monolithic-bundle-op selfward-operation
- #+(or clasp ecl mkcl) link-op #+(or clasp ecl mkcl) gather-operation)
- ((bundle-type :initform :image :allocation :class)
- (gather-operation :initform 'lib-op :allocation :class)
- #+(or clasp ecl mkcl) (gather-type :initform :static-library :allocation :class)
- (selfward-operation :initform '(#-(or clasp ecl mkcl) load-op) :allocation :class))
- (:documentation "create an image file from the system and its dependencies"))
- (defclass program-op (image-op)
- ((bundle-type :initform :program :allocation :class))
- (:documentation "create an executable file from the system and its dependencies"))
- ;; From the ASDF-internal bundle-type identifier, get a filesystem-usable pathname type.
- (defun bundle-pathname-type (bundle-type)
- (etypecase bundle-type
- ((or null string) ;; pass through nil or string literal
- bundle-type)
- ((eql :no-output-file) ;; marker for a bundle-type that has NO output file
- (error "No output file, therefore no pathname type"))
- ((eql :fasl) ;; the type of a fasl
- #-(or clasp ecl mkcl) (compile-file-type) ; on image-based platforms, used as input and output
- #+(or clasp ecl mkcl) "fasb") ; on C-linking platforms, only used as output for system bundles
- ((member :image)
- #+allegro "dxl"
- #+(and clisp os-windows) "exe"
- #-(or allegro (and clisp os-windows)) "image")
- ;; NB: on CLASP and ECL these implementations, we better agree with
- ;; (compile-file-type :type bundle-type))
- ((eql :object) ;; the type of a linkable object file
- (os-cond ((os-unix-p) "o")
- ((os-windows-p) (if (featurep '(:or :mingw32 :mingw64)) "o" "obj"))))
- ((member :lib :static-library) ;; the type of a linkable library
- (os-cond ((os-unix-p) "a")
- ((os-windows-p) (if (featurep '(:or :mingw32 :mingw64)) "a" "lib"))))
- ((member :dll :shared-library) ;; the type of a shared library
- (os-cond ((os-macosx-p) "dylib") ((os-unix-p) "so") ((os-windows-p) "dll")))
- ((eql :program) ;; the type of an executable program
- (os-cond ((os-unix-p) nil) ((os-windows-p) "exe")))))
- ;; Compute the output-files for a given bundle action
- (defun bundle-output-files (o c)
- (let ((bundle-type (bundle-type o)))
- (unless (or (eq bundle-type :no-output-file) ;; NIL already means something regarding type.
- (and (null (input-files o c)) (not (member bundle-type '(:image :program)))))
- (let ((name (or (component-build-pathname c)
- (let ((suffix
- (unless (typep o 'program-op)
- ;; "." is no good separator for Logical Pathnames, so we use "--"
- (if (operation-monolithic-p o)
- "--all-systems"
- ;; These use a different type .fasb or .a instead of .fasl
- #-(or clasp ecl mkcl) "--system"))))
- (format nil "~A~@[~A~]" (component-name c) suffix))))
- (type (bundle-pathname-type bundle-type)))
- (values (list (subpathname (component-pathname c) name :type type))
- (eq (class-of o) (coerce-class (component-build-operation c)
- :package :asdf/interface
- :super 'operation
- :error nil)))))))
- (defmethod output-files ((o bundle-op) (c system))
- (bundle-output-files o c))
- #-(or clasp ecl mkcl)
- (progn
- (defmethod perform ((o image-op) (c system))
- (dump-image (output-file o c) :executable (typep o 'program-op)))
- (defmethod perform :before ((o program-op) (c system))
- (setf *image-entry-point* (ensure-function (component-entry-point c)))))
- (defclass compiled-file (file-component)
- ((type :initform #-(or clasp ecl mkcl) (compile-file-type) #+(or clasp ecl mkcl) "fasb"))
- (:documentation "Class for a file that is already compiled,
- e.g. as part of the implementation, of an outer build system that calls into ASDF,
- or of opaque libraries shipped along the source code."))
- (defclass precompiled-system (system)
- ((build-pathname :initarg :fasl))
- (:documentation "Class For a system that is delivered as a precompiled fasl"))
- (defclass prebuilt-system (system)
- ((build-pathname :initarg :static-library :initarg :lib
- :accessor prebuilt-system-static-library))
- (:documentation "Class for a system delivered with a linkable static library (.a/.lib)")))
- ;;;
- ;;; BUNDLE-OP
- ;;;
- ;;; This operation takes all components from one or more systems and
- ;;; creates a single output file, which may be
- ;;; a FASL, a statically linked library, a shared library, etc.
- ;;; The different targets are defined by specialization.
- ;;;
- (when-upgrading (:version "3.2.0")
- ;; Cancel any previously defined method
- (defmethod initialize-instance :after ((instance bundle-op) &rest initargs &key &allow-other-keys)
- (declare (ignore initargs))))
- (with-upgradability ()
- (defgeneric trivial-system-p (component))
- (defun user-system-p (s)
- (and (typep s 'system)
- (not (builtin-system-p s))
- (not (trivial-system-p s)))))
- (eval-when (#-lispworks :compile-toplevel :load-toplevel :execute)
- (deftype user-system () '(and system (satisfies user-system-p))))
- ;;;
- ;;; First we handle monolithic bundles.
- ;;; These are standalone systems which contain everything,
- ;;; including other ASDF systems required by the current one.
- ;;; A PROGRAM is always monolithic.
- ;;;
- ;;; MONOLITHIC SHARED LIBRARIES, PROGRAMS, FASL
- ;;;
- (with-upgradability ()
- (defun direct-dependency-files (o c &key (test 'identity) (key 'output-files) &allow-other-keys)
- ;; This function selects output files from direct dependencies;
- ;; your component-depends-on method must gather the correct dependencies in the correct order.
- (while-collecting (collect)
- (map-direct-dependencies
- t o c #'(lambda (sub-o sub-c)
- (loop :for f :in (funcall key sub-o sub-c)
- :when (funcall test f) :do (collect f))))))
- (defun pathname-type-equal-function (type)
- #'(lambda (p) (equalp (pathname-type p) type)))
- (defmethod input-files ((o gather-operation) (c system))
- (unless (eq (bundle-type o) :no-output-file)
- (direct-dependency-files
- o c :key 'output-files
- :test (pathname-type-equal-function (bundle-pathname-type (gather-type o))))))
- ;; Find the operation that produces a given bundle-type
- (defun select-bundle-operation (type &optional monolithic)
- (ecase type
- ((:dll :shared-library)
- (if monolithic 'monolithic-dll-op 'dll-op))
- ((:lib :static-library)
- (if monolithic 'monolithic-lib-op 'lib-op))
- ((:fasl)
- (if monolithic 'monolithic-compile-bundle-op 'compile-bundle-op))
- ((:image)
- 'image-op)
- ((:program)
- 'program-op))))
- ;;;
- ;;; LOAD-BUNDLE-OP
- ;;;
- ;;; This is like ASDF's LOAD-OP, but using bundle fasl files.
- ;;;
- (with-upgradability ()
- (defmethod component-depends-on ((o load-bundle-op) (c system))
- `((,o ,@(component-sideway-dependencies c))
- (,(if (user-system-p c) 'compile-bundle-op 'load-op) ,c)
- ,@(call-next-method)))
- (defmethod input-files ((o load-bundle-op) (c system))
- (when (user-system-p c)
- (output-files (find-operation o 'compile-bundle-op) c)))
- (defmethod perform ((o load-bundle-op) (c system))
- (when (input-files o c)
- (perform-lisp-load-fasl o c)))
- (defmethod mark-operation-done :after ((o load-bundle-op) (c system))
- (mark-operation-done (find-operation o 'load-op) c)))
- ;;;
- ;;; PRECOMPILED FILES
- ;;;
- ;;; This component can be used to distribute ASDF systems in precompiled form.
- ;;; Only useful when the dependencies have also been precompiled.
- ;;;
- (with-upgradability ()
- (defmethod trivial-system-p ((s system))
- (every #'(lambda (c) (typep c 'compiled-file)) (component-children s)))
- (defmethod input-files ((o operation) (c compiled-file))
- (list (component-pathname c)))
- (defmethod perform ((o load-op) (c compiled-file))
- (perform-lisp-load-fasl o c))
- (defmethod perform ((o load-source-op) (c compiled-file))
- (perform (find-operation o 'load-op) c))
- (defmethod perform ((o operation) (c compiled-file))
- nil))
- ;;;
- ;;; Pre-built systems
- ;;;
- (with-upgradability ()
- (defmethod trivial-system-p ((s prebuilt-system))
- t)
- (defmethod perform ((o link-op) (c prebuilt-system))
- nil)
- (defmethod perform ((o basic-compile-bundle-op) (c prebuilt-system))
- nil)
- (defmethod perform ((o lib-op) (c prebuilt-system))
- nil)
- (defmethod perform ((o dll-op) (c prebuilt-system))
- nil)
- (defmethod component-depends-on ((o gather-operation) (c prebuilt-system))
- nil)
- (defmethod output-files ((o lib-op) (c prebuilt-system))
- (values (list (prebuilt-system-static-library c)) t)))
- ;;;
- ;;; PREBUILT SYSTEM CREATOR
- ;;;
- (with-upgradability ()
- (defmethod output-files ((o deliver-asd-op) (s system))
- (list (make-pathname :name (component-name s) :type "asd"
- :defaults (component-pathname s))))
- (defmethod perform ((o deliver-asd-op) (s system))
- (let* ((inputs (input-files o s))
- (fasl (first inputs))
- (library (second inputs))
- (asd (first (output-files o s)))
- (name (if (and fasl asd) (pathname-name asd) (return-from perform)))
- (version (component-version s))
- (dependencies
- (if (operation-monolithic-p o)
- ;; We want only dependencies, and we use basic-load-op rather than load-op so that
- ;; this will keep working on systems when *load-system-operation* is load-bundle-op
- (remove-if-not 'builtin-system-p
- (required-components s :component-type 'system
- :keep-operation 'basic-load-op))
- (while-collecting (x) ;; resolve the sideway-dependencies of s
- (map-direct-dependencies
- t 'load-op s
- #'(lambda (o c)
- (when (and (typep o 'load-op) (typep c 'system))
- (x c)))))))
- (depends-on (mapcar 'coerce-name dependencies)))
- (when (pathname-equal asd (system-source-file s))
- (cerror "overwrite the asd file"
- "~/asdf-action:format-action/ is going to overwrite the system definition file ~S ~
- which is probably not what you want; you probably need to tweak your output translations."
- (cons o s) asd))
- (with-open-file (s asd :direction :output :if-exists :supersede
- :if-does-not-exist :create)
- (format s ";;; Prebuilt~:[~; monolithic~] ASDF definition for system ~A~%"
- (operation-monolithic-p o) name)
- (format s ";;; Built for ~A ~A on a ~A/~A ~A~%"
- (lisp-implementation-type)
- (lisp-implementation-version)
- (software-type)
- (machine-type)
- (software-version))
- (let ((*package* (find-package :asdf-user)))
- (pprint `(defsystem ,name
- :class prebuilt-system
- :version ,version
- :depends-on ,depends-on
- :components ((:compiled-file ,(pathname-name fasl)))
- ,@(when library `(:lib ,(file-namestring library))))
- s)
- (terpri s)))))
- #-(or clasp ecl mkcl)
- (defmethod perform ((o basic-compile-bundle-op) (c system))
- (let* ((input-files (input-files o c))
- (fasl-files (remove (compile-file-type) input-files :key #'pathname-type :test-not #'equalp))
- (non-fasl-files (remove (compile-file-type) input-files :key #'pathname-type :test #'equalp))
- (output-files (output-files o c))
- (output-file (first output-files)))
- (assert (eq (not input-files) (not output-files)))
- (when input-files
- (when non-fasl-files
- (error "On ~A, asdf/bundle can only bundle FASL files, but these were also produced: ~S"
- (implementation-type) non-fasl-files))
- (when (or (prologue-code c) (epilogue-code c))
- (error "prologue-code and epilogue-code are not supported on ~A"
- (implementation-type)))
- (with-staging-pathname (output-file)
- (combine-fasls fasl-files output-file)))))
- (defmethod input-files ((o load-op) (s precompiled-system))
- (bundle-output-files (find-operation o 'compile-bundle-op) s))
- (defmethod perform ((o load-op) (s precompiled-system))
- (perform-lisp-load-fasl o s))
- (defmethod component-depends-on ((o load-bundle-op) (s precompiled-system))
- #+xcl (declare (ignorable o))
- `((load-op ,s) ,@(call-next-method))))
- #| ;; Example use:
- (asdf:defsystem :precompiled-asdf-utils :class asdf::precompiled-system :fasl (asdf:apply-output-translations (asdf:system-relative-pathname :asdf-utils "asdf-utils.system.fasl")))
- (asdf:load-system :precompiled-asdf-utils)
- |#
- #+(or clasp ecl mkcl)
- (with-upgradability ()
- #+ecl ;; doesn't work on clasp or mkcl (yet?).
- (unless (use-ecl-byte-compiler-p)
- (setf *load-system-operation* 'load-bundle-op))
- (defun system-module-pathname (module)
- (let ((name (coerce-name module)))
- (some
- 'file-exists-p
- (list
- #+clasp (compile-file-pathname (make-pathname :name name :defaults "sys:") :output-type :object)
- #+ecl (compile-file-pathname (make-pathname :name name :defaults "sys:") :type :lib)
- #+ecl (compile-file-pathname (make-pathname :name name :defaults "sys:") :type :object)
- #+mkcl (make-pathname :name name :type (bundle-pathname-type :lib) :defaults #p"sys:")
- #+mkcl (make-pathname :name name :type (bundle-pathname-type :lib) :defaults #p"sys:contrib;")))))
- (defun make-prebuilt-system (name &optional (pathname (system-module-pathname name)))
- "Creates a prebuilt-system if PATHNAME isn't NIL."
- (when pathname
- (make-instance 'prebuilt-system
- :name (coerce-name name)
- :static-library (resolve-symlinks* pathname))))
- (defmethod component-depends-on :around ((o image-op) (c system))
- (destructuring-bind ((lib-op . deps)) (call-next-method)
- (labels ((has-it-p (x) (find x deps :test 'equal :key 'coerce-name))
- (ensure-linkable-system (x)
- (unless (has-it-p x)
- (or (if-let (s (find-system x))
- (and (system-source-directory x)
- (list s)))
- (if-let (p (system-module-pathname x))
- (list (make-prebuilt-system x p)))))))
- `((,lib-op
- ,@(unless (no-uiop c)
- (append (ensure-linkable-system "cmp")
- (or (ensure-linkable-system "uiop")
- (ensure-linkable-system "asdf"))))
- ,@deps)))))
- (defmethod perform ((o link-op) (c system))
- (let* ((object-files (input-files o c))
- (output (output-files o c))
- (bundle (first output))
- (programp (typep o 'program-op))
- (kind (bundle-type o)))
- (when output
- (apply 'create-image
- bundle (append
- (when programp (prefix-lisp-object-files c))
- object-files
- (when programp (postfix-lisp-object-files c)))
- :kind kind
- :prologue-code (when programp (prologue-code c))
- :epilogue-code (when programp (epilogue-code c))
- :build-args (when programp (extra-build-args c))
- :extra-object-files (when programp (extra-object-files c))
- :no-uiop (no-uiop c)
- (when programp `(:entry-point ,(component-entry-point c))))))))
|