mirror of
https://gitlab.com/embeddable-common-lisp/ecl.git
synced 2025-12-06 02:40:26 -08:00
cmp: add support for precompiled header files
Improves compilation speed for single functions by about 40-50 percent. Precompiled headers are specific to the compiler version and options in use. Due to this, we regenerate the header whenever the compiler configuration changes.
This commit is contained in:
parent
46e158e912
commit
636cb4cf60
4 changed files with 87 additions and 0 deletions
|
|
@ -32,6 +32,9 @@
|
||||||
** Enhancements
|
** Enhancements
|
||||||
** Issues fixed
|
** Issues fixed
|
||||||
- The generational and precise garbage collector modes work again
|
- The generational and precise garbage collector modes work again
|
||||||
|
- ECL can now use precompiled headers to speed up compilation. Use ~(setq
|
||||||
|
c::*use-precompiled-headers* nil)~ to disable this feature
|
||||||
|
** Issues fixed
|
||||||
** API changes
|
** API changes
|
||||||
* 20.4.24 changes since 16.1.3
|
* 20.4.24 changes since 16.1.3
|
||||||
** Announcement
|
** Announcement
|
||||||
|
|
|
||||||
|
|
@ -212,6 +212,11 @@ slashes before special characters.")
|
||||||
and standalone programs. It is not required to surround values with quotes or use
|
and standalone programs. It is not required to surround values with quotes or use
|
||||||
slashes before special characters.")
|
slashes before special characters.")
|
||||||
|
|
||||||
|
(defvar *use-precompiled-headers* #+msvc nil #-msvc t
|
||||||
|
"This variable controls whether the C compiler uses precompiled header files.")
|
||||||
|
(defvar *precompiled-header-flags* nil)
|
||||||
|
(defvar *precompiled-header-cc-config* nil)
|
||||||
|
|
||||||
;;;
|
;;;
|
||||||
;;; Compiler program and flags.
|
;;; Compiler program and flags.
|
||||||
;;;
|
;;;
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,7 @@ the environment variable TMPDIR to a different value." template))
|
||||||
(:program (setf format +executable-file-format+))
|
(:program (setf format +executable-file-format+))
|
||||||
#+msvc
|
#+msvc
|
||||||
(:import-library (setf extension "implib"))
|
(:import-library (setf extension "implib"))
|
||||||
|
(:precompiled-header (setf format #-msvc "~a.h.gch" #+msvc "~a.pch"))
|
||||||
((:fasl :fas) (setf extension "fas")))
|
((:fasl :fas) (setf extension "fas")))
|
||||||
(cond ((not (member output-file '(T NIL)))
|
(cond ((not (member output-file '(T NIL)))
|
||||||
output-file)
|
output-file)
|
||||||
|
|
@ -973,6 +974,7 @@ from the C language code. NIL means \"do not create the file\"."
|
||||||
(safe-run-program
|
(safe-run-program
|
||||||
*cc*
|
*cc*
|
||||||
`("-I."
|
`("-I."
|
||||||
|
,@(precompiled-header-flags)
|
||||||
,(concatenate 'string "-I" (fix-for-mingw (ecl-include-directory)))
|
,(concatenate 'string "-I" (fix-for-mingw (ecl-include-directory)))
|
||||||
,@(split-program-options *cc-flags*)
|
,@(split-program-options *cc-flags*)
|
||||||
,@(and (>= (cmp-env-optimization 'speed) 2)
|
,@(and (>= (cmp-env-optimization 'speed) 2)
|
||||||
|
|
@ -1001,6 +1003,78 @@ from the C language code. NIL means \"do not create the file\"."
|
||||||
(declare (ignore options))
|
(declare (ignore options))
|
||||||
`(progn ,@body))
|
`(progn ,@body))
|
||||||
|
|
||||||
|
(defun need-to-dump-precompiled-header ()
|
||||||
|
(let* ((config *precompiled-header-cc-config*)
|
||||||
|
(need-to-dump (or (null config)
|
||||||
|
(not (eq (svref config 0) *cc*))
|
||||||
|
(not (eq (svref config 1) (ecl-include-directory)))
|
||||||
|
(not (eq (svref config 2) *cc-flags*))
|
||||||
|
(not (eq (svref config 3) *cc-optimize*))
|
||||||
|
(not (eq (svref config 4) *user-cc-flags*)))))
|
||||||
|
(when need-to-dump
|
||||||
|
(setf *precompiled-header-cc-config*
|
||||||
|
(vector *cc* (ecl-include-directory) *cc-flags*
|
||||||
|
*cc-optimize* *user-cc-flags*)))
|
||||||
|
need-to-dump))
|
||||||
|
|
||||||
|
(defun precompiled-header-flags ()
|
||||||
|
(when *use-precompiled-headers*
|
||||||
|
(when (need-to-dump-precompiled-header)
|
||||||
|
(handler-case
|
||||||
|
(dump-precompiled-header)
|
||||||
|
(error (err)
|
||||||
|
(setf *use-precompiled-headers* nil
|
||||||
|
*precompiled-header-flags* nil
|
||||||
|
*precompiled-header-cc-config* nil)
|
||||||
|
(cmpnote "Disabling precompiled header files due to error:~% ~A" err))))
|
||||||
|
*precompiled-header-flags*))
|
||||||
|
|
||||||
|
#+msvc
|
||||||
|
(defun dump-precompiled-header ()
|
||||||
|
;; The way precompiled headers work on msvc is not compatible with
|
||||||
|
;; what we want to use them for. The msvc compiler creates a
|
||||||
|
;; precompiled header file out of ordinary source files by
|
||||||
|
;; processing them up to a certain point at which all needed headers
|
||||||
|
;; are included. This creates both a precompiled header and a object
|
||||||
|
;; file. The object file created by this compilation must be
|
||||||
|
;; included in all binaries which are linked together from other
|
||||||
|
;; source files compiled using the precompiled header. Thus, we
|
||||||
|
;; would need to include the first object file created in a session
|
||||||
|
;; in all further object files if we wanted to support that.
|
||||||
|
(error "Precompiled headers are not supported for msvc."))
|
||||||
|
|
||||||
|
#-msvc
|
||||||
|
(defun dump-precompiled-header ()
|
||||||
|
(let* ((input-file (make-pathname
|
||||||
|
:directory (append (pathname-directory (ecl-include-directory))
|
||||||
|
'("ecl"))
|
||||||
|
:defaults (ecl-include-directory)
|
||||||
|
:name "ecl-cmp"
|
||||||
|
:type "h"))
|
||||||
|
(output-dir (merge-pathnames
|
||||||
|
(format nil "ecl-include~4,'0x/" (random #xffff))
|
||||||
|
(translate-logical-pathname "TMP:")))
|
||||||
|
(output-file (compile-file-pathname
|
||||||
|
(make-pathname :name "ecl-cmp" :defaults output-dir)
|
||||||
|
:type :precompiled-header)))
|
||||||
|
(ensure-directories-exist output-dir)
|
||||||
|
(push output-dir *files-to-be-deleted*)
|
||||||
|
(safe-run-program
|
||||||
|
*cc*
|
||||||
|
`("-x" "c-header"
|
||||||
|
,(fix-for-mingw (namestring input-file))
|
||||||
|
,(concatenate 'string "-I" (fix-for-mingw (ecl-include-directory)))
|
||||||
|
,@(split-program-options *cc-flags*)
|
||||||
|
,@(split-program-options *cc-optimize*)
|
||||||
|
"-o"
|
||||||
|
,(fix-for-mingw (namestring output-file))
|
||||||
|
,@(split-program-options *user-cc-flags*)))
|
||||||
|
(push output-file *files-to-be-deleted*)
|
||||||
|
(setf *precompiled-header-flags*
|
||||||
|
(list (concatenate 'string "-I" (namestring output-dir))
|
||||||
|
"-include"
|
||||||
|
(concatenate 'string (namestring output-dir) "ecl-cmp.h")))))
|
||||||
|
|
||||||
(ext:package-lock "CL" t)
|
(ext:package-lock "CL" t)
|
||||||
|
|
||||||
(setf *features* (delete :ecl-bytecmp *features*))
|
(setf *features* (delete :ecl-bytecmp *features*))
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,9 @@
|
||||||
See file '../Copyright' for full details.
|
See file '../Copyright' for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef ECL_CMP_H
|
||||||
|
#define ECL_CMP_H
|
||||||
|
|
||||||
#ifndef __CYGWIN__
|
#ifndef __CYGWIN__
|
||||||
/* Recent versions of cygwin do not define fd_set when WINSOCKAPI is
|
/* Recent versions of cygwin do not define fd_set when WINSOCKAPI is
|
||||||
* defined */
|
* defined */
|
||||||
|
|
@ -61,3 +64,5 @@ struct ecl_var_debug_info {
|
||||||
|
|
||||||
#define _ecl_check_narg(n) \
|
#define _ecl_check_narg(n) \
|
||||||
do { if (ecl_unlikely(narg != (n))) FEwrong_num_arguments_anonym();} while(0)
|
do { if (ecl_unlikely(narg != (n))) FEwrong_num_arguments_anonym();} while(0)
|
||||||
|
|
||||||
|
#endif /* ECL_CMP_H */
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue