From f2af40a83fd7b8ac719622cf1b95f9c8198587a4 Mon Sep 17 00:00:00 2001 From: felix Date: Sun, 9 Dec 2018 13:20:00 +0100 Subject: [PATCH] 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/.lib 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 that the egg-build has access to the static linker and required options --- chicken-install.scm | 2 + csc.scm | 14 +- defaults.make | 9 ++ egg-compile.scm | 298 ++++++++++++++++++++++++++++++++++------ egg-environment.scm | 3 + manual/Egg specification format | 20 +++ 6 files changed, 297 insertions(+), 49 deletions(-) diff --git a/chicken-install.scm b/chicken-install.scm index 4f6e99c5..a04789a8 100644 --- a/chicken-install.scm +++ b/chicken-install.scm @@ -184,12 +184,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 83d1d2c4..a11b5110 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: @@ -497,7 +503,7 @@ Usage: #{csc} [OPTION ...] [FILENAME ...] on this platform) -no-elevation embed manifest on Windows to supress elevation warnings for programs named `install' or `setup' - + Options can be collapsed if unambiguous, so -vkfO 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..06a11bf6 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+ ".lib") (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)) @@ -194,7 +205,10 @@ (when (eq? #t ifile) (set! ifile rtarget)) (addfiles (if (memq 'static link) - (list (conc dest "/" rtarget objext) + (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))) @@ -533,7 +602,7 @@ (print "\n" (qs* default-builder platform #t) " " (joins targets) " : " src " " (qs* eggfile platform) " " - (if custom cmd "") " " + (if custom (qs* cmd platform) "") " " (filelist srcdir source-dependencies platform) " : " cmd (if keep-generated-files " -k" "") @@ -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..142ae15c 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) -- 2.16.2