2014-09-10 2 views
2

Я пытался создать исполняемый файл с использованием lisp-кода. Но я не могу скомпилировать LISP файла на всех, потому что нет hellowolrd пакета перед загрузкой helloworld системыНевозможно использовать lisp-пакеты, определенные в системе

;; test.lisp 
(asdf:load-system :helloworld) 

(defun main() 
    (helloworld:start)) 


Конечно, я сделал систему helloworld и положить его в ~/quicklisp/local-projects/. helloworld система успешно загружена без ошибок.

;; ~/quicklisp/local-projects/helloworld/helloworld.asd 
(asdf:defsystem helloworld 
    :version "1.0" 
    :components ((:file "package"))) 

;; ~/quicklisp/local-projects/helloworld/package.lisp 
(defpackage :helloworld 
    (:use :common-lisp :asdf) 
    (:export :start)) 

(in-package :helloworld) 
(defun start() 
    (format t "Welcome, ASDF")) 


Я хочу собрать test.lisp без явной загрузки. Я также пробовал use-package и defpackage, но не смог.

;; test.lisp 
(asdf:load-system :helloworld) 
(use-package :helloworld) 

(defun main() 
    (helloworld:start)) 


;; test.lisp 
(asdf:load-system :helloworld) 

(defpackage :test 
    (:use :cl :asdf) 
    (:export :main)) 

(in-package :test) 

(defun main() 
    (helloworld:start)) 


Как я могу использовать helloworld пакет, определенный в helloworld системе без его загрузки? Должен ли я создать новую систему с использованием системы helloworld?

+0

(ql: quickload 'helloworld) работает нормально? Какая у вас ошибка? – coredump

+0

Существует дубликат этого вопроса. Но где? –

ответ

5

В этом коде есть кое-что интересное происходит:

;; test.lisp 
(asdf:load-system :helloworld) 

(defun main() 
    (helloworld:start)) 

Вы не можете скомпилировать его в целом, потому что, как вы отметили, пытаясь прочитать символ hellowworld:start проблема , потому что пока нет пакета helloworld. Чтобы прочитать символ, вам, по крайней мере, необходимо определить пакет. Но тогда почему мы не получаем ту же проблему с (asdf:load-system :helloworld)? Просто пакет ASDF уже определен (либо реализация включает его, либо вы уже загрузили, либо что-то еще. Одна вещь, которую вы могли бы сделать, заключается в том, чтобы убедиться, что во время компиляции вы уже загрузили вашу систему helloworld :.

;; test.lisp 
(eval-when (:compile-toplevel) 
    (asdf:load-system :helloworld)) 

(defun main() 
    (helloworld:start)) 

Это должно позволить вам скомпилировать файл, так как вы будете оценивать форму загрузки при компиляции, а затем пакет будет определяться по времени вы определяете main

конечно, теперь вы У меня есть скомпилированный файл, но что произойдет, если вы загрузите его в новый экземпляр Lisp, где система helloworld не была загружена? У вас будет проблема. Поэтому вы действительно хотите загрузить эту систему, когда вы также загружаете файл, и, вероятно, если вы просто выполняете формы из файла (например, если вы читаете формы по одному и оцениваете их). Таким образом, вы, вероятно, хотите, чтобы оценить, что нагрузка-системы еще в двух контекстах:

;; test.lisp 
(eval-when (:compile-toplevel :load-toplevel :execute) 
    (asdf:load-system :helloworld)) 

(defun main() 
    (helloworld:start)) 

Все, что сказал, не забудьте рассмотреть, является ли наиболее подходящим способом для загрузки системы в этом случае. Это может иметь смысл, если по какой-то причине вы пытаетесь сохранить весь код в одном файле или создать сценарий доставки. Если, с другой стороны, вы создаете другую загружаемую систему ASDF, тогда вы, вероятно, просто включите helloworld в качестве зависимости, и пусть ASDF обработает загрузку зависимостей.

1

Если вы хотите скомпилировать двоичный файл, вы можете использовать для этого простой скрипт Lisp, e. г.(При условии, SBCL)

;;;; build.lisp 
(require "asdf") 
(asdf:operate 'asdf:load-op "helloworld") 
(sb-ext:save-lisp-and-die "helloworld" 
          :toplevel helloworld:start 
          :executable t) 

Makefile:

all: 
    sbcl --load build.lisp 

При загрузке файла, Лисп следовательно выполняет свои формы, так что к тому времени он прибыл в save-lisp-and-die он уже знает о helloworld пакете.

Существуют также специальные инструменты для создания исполняемых файлов, buildapp и cl-launch. Последний может создавать исполняемые скрипты и работать с сохраненными ядрами.

UPD

Да, исполняемый файл, построенный таким образом, будет содержать весь Лисп, поэтому 1) это будет огромным; 2) наличие двух или более таких исполняемых файлов означает, что у вас есть (вероятно, лишние) копии всего Lisp.

Другая реализация может производить меньшие двоичные файлы, e. г. CLISP; они говорят, что коммерческие еще лучше.

Для целевых компьютеров, не предназначенных для Lisp, это единственно возможное решение. Напротив, если у целевого компьютера есть компилятор Lisp, есть еще два варианта: скрипты и сохраненные ядра.

Вы можете сделать сценарий оболочки, вызывающий sbcl --load <file>, или использовать cl-launch для получения сложной оболочки оболочки, которая может быть такой же переносной, как вы этого хотите. SBCL и CLISP поддерживают также shebang.

Однако, если время запуска имеет значение, загрузка библиотек будет узким местом, хотя они скомпилированы только один раз. В этом случае вы можете обойтись, используя обычное ядро ​​, или image. Ядро можно рассматривать как сохраненное состояние мира Лиспа, а сохранение ядра - основная задача sb-ext:save-lisp-and-die и его коллег. Загрузка ядра происходит быстро, и у вас сразу есть все библиотеки, скомпилированные в нем. Но опять же размер становится значительным, хотя и не таким огромным, как в случае автономного исполняемого файла. Естественно, одно ядро ​​может использоваться для нескольких приложений. Cl-launch может работать и с ядрами; в частности, он позволяет удобно определять функцию входа.

+0

Спасибо. Но у меня есть еще один вопрос. Исполняемый файл, созданный из вашего кода, кажется, содержит 'REPL'. Я имею в виду интерпретатор Lisp, среду и другие вещи. Примерно ~ 54 МБ. Должен ли я создавать большой файл при создании исполняемых файлов? – 1ambda

2

1 Чтобы иметь файл, который может быть скомпилирован и загружен, используйте eval-when. Смотрите мою статью http://fare.livejournal.com/146698.html

2- я рекомендую использовать CL-старт:

CL-пусковом -sP HelloWorld -r -o начать Helloworld -d!

3- Если вы не хотите тратить 60 МБ в пространстве, но вместо этого можете стоять от полутора секунд до нескольких секунд задержки запуска, используйте сценарий #!/Usr/bin/cl.

Смежные вопросы