Common Lisp, asdf, tests, compile system with different optimization levels

不羁岁月 提交于 2019-12-07 08:57:19

问题


What I really want is the in-source tests definitions:

Let's suppose I have an asdf system:

(defsystem simple-system
  :serial t
  :components ((:module "src"
                        :components
                        ((:file "0-package")
                         (:file "1-tests-stubs")
                         (:file "2-code") ...))))

And another system to test the first:

(defsystem simple-system-tests
  :serial t
  :components ((:module "src"
                        :components
                        ((:file "0-package")
                         (:file "1-tests-real")
                         (:file "2-code") ...))))

The only difference between them is that in the simple-system I have 1-tests-stubs where in the simple-system-tests I have 1-tests-real. In 1-tests-stubs I define a macro (defmacro def-test (&rest _args) nil) which gets a 'real' implementation in the 1-tests-real.

Now I want to compile the simple-system with (declare (optimize (safety 0) (debug 0) (speed 3))) and the simple-system-tests with the opposite (declare (optimize (safety 3) (debug 3) (speed 0))).

How can I do that(where to put and how to set these declarations in a generic way for these two systems)?

How can I reuse the definition of simple-system in the simple-system-tests (not to repeat myself retyping all modules/components)?

And I must be sure that all files are recompiled with different optimization levels for each system.

Also, it would be great if for each system files will be recompiled only if they were changed(Own copy of compiled files for each system?).


回答1:


 Optimization levels

You can try using :around-compile:

(defsystem simple-system
  :serial t
  :around-compile (lambda (next)
                    (proclaim '(optimize (debug 3) 
                                         (safety 3)
                                         (debug 3)
                                         (speed 0)))
                    (funcall next))
  :components ((:module "src"
                        :components
                        (...))))

The documentation says (emphasis mine):

Using this hook, you may achieve such effects as: locally renaming packages, binding *readtables* and other syntax-controlling variables, handling warnings and other conditions, proclaiming consistent optimization settings, saving code coverage information, maintaining meta-data about compilation timings, setting gensym counters and PRNG seeds and other sources of non-determinism, overriding the source-location and/or timestamping systems, checking that some compile-time side-effects were properly balanced, etc.

The action is performed around each file that is being compiled in the system; you can shadow the value of :around-compile for all files in a module, or specific files.




回答2:


Optimization with low safety.

Generally I would not recommend to compile a whole system (a library or application) with zero safety like this:

(declare (optimize (safety 0) (debug 0) (speed 3)))

Using zero safety in combination to type declarations may alter semantics of the program and errors may crash the program. It might even open up security holes.

My recommendation for production code is this:

  • optimize speed critical parts with speed = 3 and leave the usual safety settings (2 or 3).

  • if a low safety setting then is needed for even further speed improvements, declare it only where it is needed. Common Lisp provides function local declarations and also a special operator locally where one further can restrict the code area where declarations apply.

Making optimization settings changeable

* (defparameter *safety* 0)

This does not work, because safety values need to be numbers:

*SAFETY*
* (defun foo (a) (declare (optimize (safety *safety*))) (1+ a))
; in: DEFUN FOO
;     (OPTIMIZE (SAFETY *SAFETY*))
; 
; caught WARNING:
;   Ignoring bad optimization value *SAFETY* in: (OPTIMIZE (SAFETY *SAFETY*))
; 
; compilation unit finished
;   caught 1 WARNING condition

FOO

But this works, using read-time evaluation:

* (defun foo (a) (declare (optimize (safety #.*safety*))) (1+ a))
WARNING: redefining COMMON-LISP-USER::FOO in DEFUN

FOO

One can also insert whole declarations:

* (defparameter *optimization-declaration* '(declare (optimize (safety 0))))

*OPTIMIZATION-DECLARATION*
* (defun foo (a) #.*optimization-declaration* (1+ a))
WARNING: redefining COMMON-LISP-USER::FOO in DEFUN

FOO
* 



回答3:


I hope it's just a typo that in these examples, the same file 0-package is shared by two systems. If it isn't, you're going to lose badly and it will be all your fault.



来源:https://stackoverflow.com/questions/45730012/common-lisp-asdf-tests-compile-system-with-different-optimization-levels

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!