Potential Shared Library Extract
jmercouris opened this issue · 0 comments
jmercouris commented
Draft source code, it should lend an idea as to how I believe it can work. Feel free to copy/modify and integrate into deploy:
(in-package :cl-user)
(uiop:define-package shared-library-extract
(:use :common-lisp))
(in-package :shared-library-extract)
(defvar *object-tool* "otool")
(defvar *cp* "cp")
(defvar *copyable-library-paths* (list "/opt/local/lib"))
(defvar *install-name-tool* "install_name_tool")
(defun object-tool (path)
(flet ((process-line (line) (first (str:split " " (str:trim line)))))
(with-input-from-string (output (uiop:run-program (list *object-tool* "-L" path)
:output '(:string :stripped t)))
(loop for line = (read-line output nil)
while (not (null line))
collect (process-line line)))))
(defun copy-library-p (library-path)
(find-if (lambda (i) (str:containsp i library-path)) *copyable-library-paths*))
(defun copy-file (from to)
(format t "Copy file ~a to ~a~%" from to)
(uiop:run-program (list *cp* from to)))
(defun file-name (path)
(car (last (str:split "/" path))))
(defun install-name (from to path)
(uiop:run-program (list *install-name-tool* "-change"
from to path)))
(defun install-names (library)
(format t "Install names for library ~a~%" library)
(loop for object in (object-tool library)
if (copy-library-p object)
do (install-name object (format nil "@executable_path/../Resources/~a" (file-name object)) library)))
(defun library-dependency-tree (library-path)
(let ((queue (object-tool library-path))
(seen-libraries))
(remove-duplicates
(loop for library = (pop queue)
while (not (null library))
if (copy-library-p library)
do (unless (find library seen-libraries :test #'equal)
(push library seen-libraries)
(setf queue (append queue (rest (object-tool library))))
(format t "Process Library: ~a ~%Depends on:~a~%" library (rest (object-tool library))))
if (copy-library-p library)
collect library)
:test #'equal)))
(defun process-library (library-path destination)
(loop for library in (library-dependency-tree library-path)
do (let ((destination-path (format nil "~a/~a" destination (file-name library))))
(copy-file library destination-path)
(install-names destination-path))))
(defun process-libraries (libraries destination)
(mapcar (lambda (i) (process-library i destination)) libraries))