~ chicken-core (chicken-5) 693e13494b9c0e0a2f3979ad8cacf2b9865439e3
commit 693e13494b9c0e0a2f3979ad8cacf2b9865439e3
Author: felix <felix@call-with-current-continuation.org>
AuthorDate: Sun Dec 9 13:20:00 2018 +0100
Commit: Evan Hanson <evhan@foldling.org>
CommitDate: Mon Dec 31 23:24:29 2018 +1300
Add c-objects component type to egg format
- Adds component type "c-object"
- Adds component property "objects" to declare linked c-object dependencies
- Extend csc to search for static library files before trying to resolve
linkable objects
- Extend egg-compilation to build static .a files instead of .o files when
building a statically linked extension
- Adds C_TARGET_LIBRARIAN and C_TARGET_LIBRARIAN_FLAGS to chicken-config.h,
so the egg-build has access to the static linker and required options
Signed-off-by: Evan Hanson <evhan@foldling.org>
diff --git a/chicken-install.scm b/chicken-install.scm
index fd18e305..3edf293b 100644
--- a/chicken-install.scm
+++ b/chicken-install.scm
@@ -182,12 +182,14 @@
(link-options #f #f #f)
(custom-build #f #f #f)
(linkage #f #f #f)
+ (objects #f #f #f)
(install-name #f #f #f ,nameprop?)
(target #f #t #f)
(host #f #t #f)
(types-file #f #f #f ,name-or-predefd?)
(inline-file #f #f #f ,optname?)
(extension #f #t #t)
+ (c-object #f #t #t)
(generated-source-file #f #t #t)
(program #f #t #t)
(data #f #t #t)
diff --git a/csc.scm b/csc.scm
index 646aa4e2..f12c9319 100644
--- a/csc.scm
+++ b/csc.scm
@@ -109,6 +109,7 @@
(define compile-output-flag "-o ")
(define shared-library-extension ##sys#load-dynamic-extension)
(define static-object-extension (##sys#string-append "static." object-extension))
+(define static-library-extension (##sys#string-append "static." library-extension))
(define default-translation-optimization-options '())
(define pic-options (if (or mingw cygwin) '("-DPIC") '("-fPIC" "-DPIC")))
(define generate-manifest #f)
@@ -295,13 +296,18 @@
(define (find-object-file name)
(let ((o (make-pathname #f name object-extension))
+ (a (make-pathname #f name library-extension))
;; In setup mode, objects in build dir may also end with "static.o"
+ (static-a (make-pathname #f name static-library-extension))
(static-o (make-pathname #f name static-object-extension)))
- (or (file-exists? o)
+ (or (file-exists? a)
+ (file-exists? o)
(and (eq? ##sys#setup-mode #t)
- (file-exists? static-o))
+ (or (file-exists? static-a)
+ (file-exists? static-o)))
(and (not ignore-repository)
- (chicken.load#find-file o (repo-path))))))
+ (or (chicken.load#find-file a (repo-path))
+ (chicken.load#find-file o (repo-path)))))))
;;; Display usage information:
diff --git a/defaults.make b/defaults.make
index 5cba3170..34bd301d 100644
--- a/defaults.make
+++ b/defaults.make
@@ -99,14 +99,17 @@ ifdef TARGETSYSTEM
TARGET_C_COMPILER ?= $(TARGETSYSTEM)-$(C_COMPILER)
TARGET_CXX_COMPILER ?= $(TARGETSYSTEM)-$(CXX_COMPILER)
TARGET_RC_COMPILER ?= $(TARGETSYSTEM)-$(RC_COMPILER)
+TARGET_LIBRARIAN ?= $(TARGETSYSTEM)-$(LIBRARIAN)
else
TARGET_C_COMPILER ?= $(C_COMPILER)
TARGET_CXX_COMPILER ?= $(CXX_COMPILER)
TARGET_RC_COMPILER ?= $(RC_COMPILER)
+TARGET_LIBRARIAN ?= $(LIBRARIAN)
endif
TARGET_C_COMPILER_OPTIONS ?= $(C_COMPILER_OPTIONS)
TARGET_C_COMPILER_OPTIMIZATION_OPTIONS ?= $(C_COMPILER_OPTIMIZATION_OPTIONS)
+TARGET_LIBRARIAN_OPTIONS ?= $(LIBRARIAN_OPTIONS)
TARGET_PREFIX ?= $(PREFIX)
TARGET_RUN_PREFIX ?= $(TARGET_PREFIX)
TARGET_LIBRARIES ?= $(LIBRARIES)
@@ -408,12 +411,18 @@ endif
$(call echo, >>, $@,#ifndef C_TARGET_RC_COMPILER)
$(call echo, >>, $@,# define C_TARGET_RC_COMPILER "$(TARGET_RC_COMPILER)")
$(call echo, >>, $@,#endif)
+ $(call echo, >>, $@,#ifndef C_TARGET_LIBRARIAN)
+ $(call echo, >>, $@,# define C_TARGET_LIBRARIAN "$(TARGET_LIBRARIAN)")
+ $(call echo, >>, $@,#endif)
$(call echo, >>, $@,#ifndef C_TARGET_INSTALL_PROGRAM)
$(call echo, >>, $@,# define C_TARGET_INSTALL_PROGRAM "$(INSTALL_PROGRAM)")
$(call echo, >>, $@,#endif)
$(call echo, >>, $@,#ifndef C_TARGET_CFLAGS)
$(call echo, >>, $@,# define C_TARGET_CFLAGS "$(TARGET_C_COMPILER_OPTIONS) $(TARGET_C_COMPILER_OPTIMIZATION_OPTIONS)")
$(call echo, >>, $@,#endif)
+ $(call echo, >>, $@,#ifndef C_TARGET_LIBRARIAN_FLAGS)
+ $(call echo, >>, $@,# define C_TARGET_LIBRARIAN_FLAGS "$(TARGET_LIBRARIAN_OPTIONS)")
+ $(call echo, >>, $@,#endif)
$(call echo, >>, $@,#ifndef C_TARGET_LDFLAGS)
$(call echo, >>, $@,# define C_TARGET_LDFLAGS "$(TARGET_LINKER_OPTIONS) $(TARGET_LINKER_OPTIMIZATION_OPTIONS)")
$(call echo, >>, $@,#endif)
diff --git a/egg-compile.scm b/egg-compile.scm
index bbf59858..c744592b 100644
--- a/egg-compile.scm
+++ b/egg-compile.scm
@@ -41,7 +41,9 @@
(define +unix-executable-extension+ "")
(define +windows-executable-extension+ ".exe")
(define +unix-object-extension+ ".o")
+(define +unix-archive-extension+ ".a")
(define +windows-object-extension+ ".obj")
+(define +windows-archive-extension+ ".a")
(define +link-file-extension+ ".link")
(define keep-generated-files #f)
@@ -61,6 +63,11 @@
((unix) +unix-object-extension+)
((windows) +windows-object-extension+)))
+(define (archive-extension platform)
+ (case platform
+ ((unix) +unix-archive-extension+)
+ ((windows) +windows-archive-extension+)))
+
(define (executable-extension platform)
(case platform
((unix) +unix-executable-extension+)
@@ -140,6 +147,7 @@
(define (compile-egg-info eggfile info version platform mode)
(let ((exts '())
(prgs '())
+ (objs '())
(data '())
(genfiles '())
(cinc '())
@@ -157,11 +165,13 @@
(lopts '())
(opts '())
(mods #f)
+ (lobjs '())
(tfile #f)
(ptfile #f)
(ifile #f)
(eggfile (locate-egg-file eggfile))
(objext (object-extension platform))
+ (arcext (archive-extension platform))
(exeext (executable-extension platform)))
(define (check-target t lst)
(when (member t lst)
@@ -183,6 +193,7 @@
(ptfile #f)
(ifile #f)
(lopts lopts)
+ (lobjs '())
(oname #f)
(mods #f)
(opts opts))
@@ -193,8 +204,11 @@
(when (eq? #t tfile) (set! tfile rtarget))
(when (eq? #t ifile) (set! ifile rtarget))
(addfiles
- (if (memq 'static link)
- (list (conc dest "/" rtarget objext)
+ (if (memq 'static link)
+ (list (conc dest "/" rtarget
+ (if (null? lobjs)
+ objext
+ arcext))
(conc dest "/" rtarget +link-file-extension+))
'())
(if (memq 'dynamic link) (list (conc dest "/" rtarget ".so")) '())
@@ -206,14 +220,44 @@
'())
(import-libraries mods dest rtarget mode))
(set! exts
- (cons (list target dependencies: cdeps source: src options: opts
+ (cons (list target
+ dependencies: cdeps
+ source: src options: opts
link-options: lopts linkage: link custom: cbuild
mode: mode types-file: tfile inline-file: ifile
predefined-types: ptfile eggfile: eggfile
modules: (or mods (list rtarget))
source-dependencies: sdeps
+ link-objects: lobjs
output-file: rtarget)
exts)))))
+ ((c-object)
+ (fluid-let ((target (check-target (cadr info) exts))
+ (cdeps '())
+ (sdeps '())
+ (src #f)
+ (cbuild #f)
+ (link default-extension-linkage)
+ (oname #f)
+ (mods #f)
+ (opts opts))
+ (for-each compile-extension/program (cddr info))
+ (let ((dest (destination-repository mode #t))
+ ;; Respect install-name if specified
+ (rtarget (or oname target)))
+ (addfiles
+ (if (memq 'static link)
+ (list (conc dest "/" rtarget objext))
+ '()))
+ (set! objs
+ (cons (list target dependencies: cdeps source: src
+ options: opts
+ linkage: link custom: cbuild
+ mode: mode
+ eggfile: eggfile
+ source-dependencies: sdeps
+ output-file: rtarget)
+ objs)))))
((data)
(fluid-let ((target (check-target (cadr info) data))
(dest #f)
@@ -280,6 +324,7 @@
(cbuild #f)
(src #f)
(link default-program-linkage)
+ (lobjs '())
(lopts lopts)
(oname #f)
(opts opts))
@@ -297,6 +342,7 @@
custom: cbuild
mode: mode output-file: rtarget
source-dependencies: sdeps
+ link-objects: lobjs
eggfile: eggfile)
prgs)))))
(else (compile-common info compile-component))))
@@ -314,6 +360,10 @@
(set! tfile
(or (null? (cdadr info))
(arg (cadr info) 1 name?)))))))
+ ((objects)
+ (let ((los (map ->string (cdr info))))
+ (set! lobjs (append lobjs los))
+ (set! cdeps (append cdeps (map ->dep los)))))
((inline-file)
(set! ifile (or (null? (cdr info)) (arg info 1 name?))))
((custom-build)
@@ -367,7 +417,9 @@
(for-each walk (cdar clauses)))
(else (loop (cdr clauses))))))
(define (->dep x)
- (if (name? x) x (error "invalid dependency" x)))
+ (if (name? x)
+ (if (symbol? x) x (string->symbol x))
+ (error "invalid dependency" x)))
(define (compile info)
(case (car info)
((components) (for-each compile-component (cdr info)))
@@ -391,6 +443,7 @@
(filter (lambda (dep)
(and (symbol? dep)
(or (assq dep exts)
+ (assq dep objs)
(assq dep data)
(assq dep cinc)
(assq dep scminc)
@@ -401,7 +454,7 @@
;; collect information
(for-each compile info)
;; sort topologically, by dependencies
- (let* ((all (append prgs exts genfiles))
+ (let* ((all (append prgs exts objs genfiles))
(order (reverse (sort-dependencies
(map (lambda (dep)
(cons (car dep)
@@ -448,6 +501,15 @@
(if (memq 'static link)
(list (apply compile-static-program data))
'())))))
+ ((assq id objs) =>
+ (lambda (data)
+ (let ((link (get-keyword linkage: (cdr data))))
+ (append (if (memq 'dynamic link)
+ (list (apply compile-dynamic-object data))
+ '())
+ (if (memq 'static link)
+ (list (apply compile-static-object data))
+ '())))))
(else
(let ((data (assq id genfiles)))
(list (apply compile-generated-file data))))))
@@ -498,6 +560,7 @@
source-dependencies
source (options '())
predefined-types eggfile
+ link-objects
custom types-file inline-file)
srcdir platform)
(let* ((cmd (qs* (or (custom-cmd custom srcdir platform)
@@ -519,12 +582,18 @@
(if inline-file
(list "-emit-inline-file" ifile)
'())))
- (out (qs* (target-file (conc sname
- ".static"
- (object-extension platform))
- mode)
- platform))
- (targets (append (list out lfile)
+ (out1 (conc sname ".static"))
+ (out2 (qs* (target-file (conc out1
+ (object-extension platform))
+ mode)
+ platform))
+ (out3 (if (null? link-objects)
+ out2
+ (qs* (target-file (conc out1
+ (archive-extension platform))
+ mode)
+ platform)))
+ (targets (append (list out3 lfile)
(maybe types-file tfile)
(maybe inline-file ifile)))
(src (qs* (or source (conc name ".scm")) platform)))
@@ -543,12 +612,24 @@
" -D compiling-extension -c -unit " name
" -D compiling-static-extension"
" -C -I" srcdir (arglist opts platform)
- " " src " -o " out)
+ " " src " -o " out2)
+ (when (pair? link-objects)
+ (let ((lobjs (filelist srcdir
+ (map (cut conc <> (object-extension platform))
+ link-objects)
+ platform)))
+ (print (qs* default-builder platform #t) " " out3 " : "
+ out2 " " lobjs " : "
+ (qs* target-librarian platform) " "
+ target-librarian-options " " out3 " " out2 " "
+ lobjs)))
(print-end-command platform)))
(define ((compile-dynamic-extension name #!key mode mode
- source (options '()) (link-options '())
+ source (options '())
+ (link-options '())
predefined-types eggfile
+ link-objects
source-dependencies modules
custom types-file inline-file)
srcdir platform)
@@ -571,28 +652,41 @@
(list "-emit-inline-file" ifile)
'())))
(out (qs* (target-file (conc sname ".so") mode) platform))
+ (src (qs* (or source (conc name ".scm")) platform))
+ (lobjs (map (lambda (lo)
+ (target-file (conc lo
+ (object-extension platform))
+ mode))
+ link-objects))
(targets (append (list out)
(maybe inline-file ifile)
(maybe types-file tfile)
(map (lambda (m)
(qs* (prefix srcdir (conc m ".import.scm"))
platform))
- modules)))
- (src (qs* (or source (conc name ".scm")) platform)))
+ modules))))
(when custom
(prepare-custom-command cmd platform))
(print "\n" (qs* default-builder platform #t) " "
- (joins targets) " : "
- src " " (qs* eggfile platform) " "
- (if custom cmd "") " "
+ (joins targets)
+ " : "
+ src " "
+ (qs* eggfile platform) " "
+ (if custom (qs* cmd platform) "") " "
+ (filelist srcdir lobjs platform) " "
(filelist srcdir source-dependencies platform)
- " : " cmd
+ " : "
+ cmd
(if keep-generated-files " -k" "")
(if (eq? mode 'host) " -host" "")
" -D compiling-extension -J -s"
- " -setup-mode -I " srcdir " -C -I" srcdir
- (arglist opts platform) (arglist link-options platform)
- " " src " -o " out)
+ " -setup-mode -I " srcdir
+ " -C -I" srcdir
+ (arglist opts platform)
+ (arglist link-options platform) " "
+ src " "
+ (filelist srcdir lobjs platform)
+ " -o " out)
(print-end-command platform)))
(define ((compile-import-library name #!key mode
@@ -607,20 +701,101 @@
(out (qs* (target-file (conc sname ".import.so") mode)
platform))
(src (qs* (conc name ".import.scm") platform)))
- (print "\n" (qs* default-builder platform #t) " " out " : "
- src (filelist srcdir source-dependencies platform)
- " : " cmd
+ (print "\n" (qs* default-builder platform #t) " "
+ out
+ " : "
+ src
+ (filelist srcdir source-dependencies platform)
+ " : "
+ cmd
(if keep-generated-files " -k" "")
" -setup-mode -s"
(if (eq? mode 'host) " -host" "")
- " -I " srcdir " -C -I" srcdir (arglist opts platform)
- (arglist link-options platform) " " src " -o " out)
+ " -I " srcdir " -C -I" srcdir
+ (arglist opts platform)
+ (arglist link-options platform) " "
+ src
+ " -o " out)
+ (print-end-command platform)))
+
+(define ((compile-static-object name #!key mode
+ source-dependencies
+ source (options '())
+ eggfile custom)
+ srcdir platform)
+ (let* ((cmd (or (custom-cmd custom srcdir platform)
+ default-csc))
+ (sname (prefix srcdir name))
+ (ssname (and source (prefix srcdir source)))
+ (opts (if (null? options)
+ default-static-compilation-options
+ options))
+ (ename (pathname-file eggfile))
+ (out (qs* (target-file (conc sname
+ ".static"
+ (object-extension platform))
+ mode)
+ platform))
+ (src (qs* (or ssname (conc sname ".c")) platform)))
+ (when custom
+ (prepare-custom-command cmd platform))
+ (print "\n" (slashify default-builder platform) " "
+ out
+ " : "
+ (filelist srcdir source-dependencies platform)
+ src " "
+ (qs* eggfile platform) " "
+ (if custom (qs* cmd platform) "")
+ " : "
+ cmd
+ " -setup-mode -static -I " srcdir
+ (if (eq? mode 'host) " -host" "")
+ " -c -C -I" srcdir
+ (arglist opts platform)
+ " " src
+ " -o " out)
+ (print-end-command platform)))
+
+(define ((compile-dynamic-object name #!key mode mode
+ source (options '())
+ eggfile
+ source-dependencies
+ custom)
+ srcdir platform)
+ (let* ((cmd (or (custom-cmd custom srcdir platform)
+ default-csc))
+ (opts (if (null? options)
+ default-dynamic-compilation-options
+ options))
+ (sname (or source name))
+ (out (qs* (target-file (conc sname
+ (object-extension platform))
+ mode)
+ platform))
+ (src (qs* (conc sname ".c") platform)))
+ (when custom
+ (prepare-custom-command cmd platform))
+ (print "\n" (slashify default-builder platform) " "
+ out
+ " : "
+ src " "
+ (qs* eggfile platform) " "
+ (if custom (qs* cmd platform) "") " "
+ (filelist srcdir source-dependencies platform)
+ " : "
+ cmd
+ (if (eq? mode 'host) " -host" "")
+ " -setup-mode -I " srcdir
+ " -c -C -I" srcdir
+ (arglist opts platform)
+ " " src
+ " -o " out)
(print-end-command platform)))
(define ((compile-dynamic-program name #!key source mode
(options '()) (link-options '())
source-dependencies
- custom eggfile)
+ custom eggfile link-objects)
srcdir platform)
(let* ((cmd (qs* (or (custom-cmd custom srcdir platform)
default-csc)
@@ -633,25 +808,40 @@
(executable-extension platform))
mode)
platform))
+ (lobjs (map (lambda (lo)
+ (target-file (conc lo
+ (object-extension platform))
+ mode))
+ link-objects))
(src (qs* (or source (conc name ".scm")) platform)))
(when custom
(prepare-custom-command cmd platform))
- (print "\n" (qs* default-builder platform #t) " " out " : "
- src " " (qs* eggfile platform) " "
- (if custom cmd "") " "
- (filelist srcdir source-dependencies platform)
- " : " cmd
+ (print "\n" (qs* default-builder platform #t) " "
+ out
+ " : "
+ src " "
+ (qs* eggfile platform) " "
+ (if custom (qs* cmd platform) "") " "
+ (filelist srcdir source-dependencies platform) " "
+ (filelist srcdir lobjs platform)
+ " : "
+ cmd
(if keep-generated-files " -k" "")
" -setup-mode"
(if (eq? mode 'host) " -host" "")
- " -I " srcdir " -C -I" srcdir (arglist opts platform)
- (arglist link-options platform) " " src " -o " out)
+ " -I " srcdir
+ " -C -I" srcdir
+ (arglist opts platform)
+ (arglist link-options platform) " "
+ src " "
+ (filelist srcdir lobjs platform)
+ " -o " out)
(print-end-command platform)))
(define ((compile-static-program name #!key source
(options '()) (link-options '())
source-dependencies
- custom mode eggfile)
+ custom mode eggfile link-objects)
srcdir platform)
(let* ((cmd (qs* (or (custom-cmd custom srcdir platform)
default-csc)
@@ -664,19 +854,34 @@
(executable-extension platform))
mode)
platform))
+ (lobjs (map (lambda (lo)
+ (target-file (conc lo
+ (object-extension platform))
+ mode))
+ link-objects))
(src (qs* (or source (conc name ".scm")) platform)))
(when custom
(prepare-custom-command cmd platform))
- (print "\n" (qs* default-builder platform #t) " " out " : "
- src " " (qs* eggfile platform) " "
- (if custom cmd "") " "
+ (print "\n" (qs* default-builder platform #t) " "
+ out
+ " : "
+ src " "
+ (qs* eggfile platform) " "
+ (if custom (qs* cmd platform) "") " "
+ (filelist srcdir lobjs platform) " "
(filelist srcdir source-dependencies platform)
- " : " cmd
+ " : "
+ cmd
(if keep-generated-files " -k" "")
(if (eq? mode 'host) " -host" "")
- " -static -setup-mode -I " srcdir " -C -I"
- srcdir (arglist opts platform)
- (arglist link-options platform) " " src " -o " out)
+ " -static -setup-mode -I " srcdir
+ " -C -I"
+ srcdir
+ (arglist opts platform)
+ (arglist link-options platform) " "
+ src " "
+ (filelist srcdir lobjs platform)
+ " -o " out)
(print-end-command platform)))
(define ((compile-generated-file name #!key source custom
@@ -695,11 +900,14 @@
;; installation operations
-(define ((install-static-extension name #!key mode output-file)
+(define ((install-static-extension name #!key mode output-file
+ link-objects)
srcdir platform)
(let* ((cmd (install-file-command platform))
(mkdir (mkdir-command platform))
- (ext (object-extension platform))
+ (ext (if (null? link-objects)
+ (object-extension platform)
+ (archive-extension platform)))
(sname (prefix srcdir name))
(out (qs* (target-file (conc sname ".static" ext) mode)
platform #t))
diff --git a/egg-environment.scm b/egg-environment.scm
index 2d3d31b0..a4609507 100644
--- a/egg-environment.scm
+++ b/egg-environment.scm
@@ -76,6 +76,9 @@ EOF
(define default-builder
(make-pathname default-bindir (foreign-value "C_CHICKEN_DO_PROGRAM" c-string)))
+(define target-librarian (foreign-value "C_TARGET_LIBRARIAN" c-string))
+(define target-librarian-options (foreign-value "C_TARGET_LIBRARIAN_FLAGS" c-string))
+
(define host-repo (foreign-value "C_INSTALL_EGG_HOME" c-string))
(define host-libdir (foreign-value "C_INSTALL_LIB_HOME" c-string))
(define host-bindir (foreign-value "C_INSTALL_BIN_HOME" c-string))
diff --git a/manual/Egg specification format b/manual/Egg specification format
index 3268f4d6..20b1dd0f 100644
--- a/manual/Egg specification format
+++ b/manual/Egg specification format
@@ -210,6 +210,19 @@ Specifies one or more Scheme include files.
Specifies an executable program.
+==== c-object
+
+ [egg property] (c-object NAME PROP ...)
+
+Specifies a compiled C/C++ object file. Usually this component type
+is required if you want to link a separately compiled C/C++ module
+with your extension or program. C-objects are compiled like Scheme
+source files with the {{csc}} tool to ensure the same C compiler
+options and toolchain is used as for regular Scheme files compiled
+to C. If you want to pass compiler-specific options to the build
+of the C object, use the {{csc-options}} property and precede
+C compiler options with {{-C}}.
+
=== Component properties
==== host
@@ -345,6 +358,13 @@ denote filenames of which the program or extension depends.
A program or extension implicitly depends on its source file and
and on the egg-specification file.
+==== objects
+
+ [egg property] (objects NAME ...)
+
+Specifies that the components of type {{c-object}} should be linked
+to this component and that the object components are dependencies.
+
==== destination
[egg property] (destination NAME)
Trap