~ chicken-core (chicken-5) f0aafa063b465b90b6414397ddd77860da6ab54e
commit f0aafa063b465b90b6414397ddd77860da6ab54e Author: Evan Hanson <evhan@foldling.org> AuthorDate: Thu Mar 31 22:06:12 2016 +1300 Commit: Peter Bex <peter@more-magic.net> CommitDate: Sun Apr 17 19:27:32 2016 +0200 Add "-link" flag for linking with objects from extensions This is a basic helper option that just adds object files for the named extensions to csc's link step (if any exist) and automatically "-uses" them as units. Signed-off-by: Peter Bex <peter@more-magic.net> diff --git a/NEWS b/NEWS index e065f789..8bb75522 100644 --- a/NEWS +++ b/NEWS @@ -12,6 +12,9 @@ - The "-scrutinize" compiler option has been removed. - The "-module" compiler option (aliased as "-m") now expects a module name. +- Tools + - The new "-link" option to csc allows linking with objects from extensions. + - Core libraries - Removed support for memory-mapped files (posix), queues (data-structures), binary-search (data-structures), scan-input-lines (utils), and diff --git a/batch-driver.scm b/batch-driver.scm index 0d319e89..740238ce 100644 --- a/batch-driver.scm +++ b/batch-driver.scm @@ -646,9 +646,8 @@ (when enable-inline-files (for-each (lambda (id) - (and-let* ((ifile (##sys#resolve-include-filename - (make-pathname #f (symbol->string id) "inline") - #f #t)) + (and-let* ((ifile (##sys#resolve-include-filename + (symbol->string id) '(".inline") #t)) ((file-exists? ifile))) (dribble "Loading inline file ~a ..." ifile) (load-inline-file ifile))) diff --git a/csc.scm b/csc.scm index 94baf6bb..3db27261 100644 --- a/csc.scm +++ b/csc.scm @@ -169,7 +169,7 @@ -emit-type-file -consult-type-file -feature -debug-level -emit-import-library - -module + -module -link -no-feature)) (define-constant shortcuts @@ -307,6 +307,26 @@ (define static-libs #f) +;;; Locate object files for linking: + +(define (find-object-files name) + + (define (locate-object-file filename repo) + (let ((f (##sys#resolve-include-filename filename '() repo))) + (and (file-exists? f) (list f)))) + + (define (static-extension-information name) + (and-let* ((info (extension-information name)) + (files (alist-ref 'static info eq?))) + (map (lambda (f) (make-pathname (repository-path) f)) files))) + + (let ((f (make-pathname #f name object-extension))) + (or (locate-object-file f #f) + (static-extension-information name) + (locate-object-file f #t) + (stop "couldn't find linked extension: ~a" name)))) + + ;;; Display usage information: (define (usage) @@ -439,6 +459,8 @@ Usage: #{csc} FILENAME | OPTION ... -e -embedded compile as embedded (don't generate `main()') -gui compile as GUI application + -link NAME link extension with compiled executable + (implies -uses) -R -require-extension NAME require extension and import in compiled code -dll -library compile multiple units into a dynamic @@ -539,6 +561,9 @@ EOF (else "-shared")) link-options)) (set! shared #t) ) + (define (collect-linked-files names) + (append-map find-object-files (string-split names ", "))) + (define (use-private-repository) (set! compile-options (cons "-DC_PRIVATE_REPOSITORY" compile-options))) @@ -651,6 +676,12 @@ EOF [(-e -embedded) (set! embedded #t) (set! compile-options (cons "-DC_EMBEDDED" compile-options)) ] + [(-link) + (check s rest) + (t-options "-uses" (car rest)) + (set! object-files + (append object-files (collect-linked-files (car rest)))) + (set! rest (cdr rest))] [(-require-extension -R) (check s rest) (t-options "-require-extension" (car rest)) diff --git a/distribution/manifest b/distribution/manifest index eb93a5fc..1ba6f9d3 100644 --- a/distribution/manifest +++ b/distribution/manifest @@ -118,6 +118,7 @@ tests/arithmetic-test.scm tests/arithmetic-test.32.expected tests/arithmetic-test.64.expected tests/library-tests.scm +tests/linking-tests.scm tests/compiler-tests.scm tests/inlining-tests.scm tests/locative-stress-test.scm diff --git a/eval.scm b/eval.scm index 635efc23..e796e192 100644 --- a/eval.scm +++ b/eval.scm @@ -1133,7 +1133,7 @@ (read read) (reverse reverse)) (lambda (fname) - (let ((path (##sys#resolve-include-filename fname #t))) + (let ((path (##sys#resolve-include-filename fname #t #f))) (when (load-verbose) (print "; including " path " ...")) (with-input-from-file path (lambda () @@ -1398,20 +1398,24 @@ (let ((string-append string-append) ) (define (exists? fname) (##sys#file-exists? fname #t #f #f)) - (lambda (fname prefer-source #!optional repo) - (define (test2 fname lst) + (lambda (fname exts repo) + (define (test-extensions fname lst) (if (null? lst) (and (exists? fname) fname) - (let ([fn (##sys#string-append fname (car lst))]) + (let ((fn (##sys#string-append fname (car lst)))) (if (exists? fn) fn - (test2 fname (cdr lst)) ) ) ) ) + (test-extensions fname (cdr lst)))))) (define (test fname) - (test2 + (test-extensions fname - (cond ((not (##sys#fudge 24)) (list source-file-extension)) ; no dload? - (prefer-source (list source-file-extension ##sys#load-dynamic-extension)) - (else (list ##sys#load-dynamic-extension source-file-extension) ) ) )) + (cond ((pair? exts) exts) ; specific list of extensions + ((not (##sys#fudge 24)) ; no dload -> source only + (list source-file-extension)) + ((not exts) ; prefer compiled + (list ##sys#load-dynamic-extension source-file-extension)) + (else ; prefer source + (list source-file-extension ##sys#load-dynamic-extension))))) (or (test fname) (let loop ((paths (if repo (##sys#append diff --git a/manual/Using the compiler b/manual/Using the compiler index c7c22a8f..33648792 100644 --- a/manual/Using the compiler +++ b/manual/Using the compiler @@ -86,6 +86,8 @@ the source text should be read from standard input. ; -keep-shadowed-macros : Do not remove macro definitions with the same name as assigned toplevel variables (the default is to remove the macro definition). +; -link NAME : Links the extension {{NAME}} with the compiled program and uses it as a unit. Multiple names may be given and should be separated by commas. + ; -local : Assume toplevel variables defined in the current compilation unit are not externally modified. This gives the compiler more opportunities for inlining. Note that this may result in counter-intuitive and non-standard behaviour: an asssignment to an exported toplevel variable executed in a different compilation unit or in evaluated code will possibly not be seen by code executing in the current compilation unit. ; -lfa2 : Does an additional lightweight flow-analysis pass on the fully optimized program to remove more type checks. diff --git a/tests/linking-tests.scm b/tests/linking-tests.scm new file mode 100644 index 00000000..feac0a05 --- /dev/null +++ b/tests/linking-tests.scm @@ -0,0 +1,7 @@ +;;; Tests linking with core units & extensions ("csc -link ...") + +(import (chicken irregex) + (reverser)) + +(unless (irregex-match '(: #\1 (+ any) #\9) (rev "987654321")) + (error "weird")) diff --git a/tests/runtests.bat b/tests/runtests.bat index 3cc5f31b..6e507dac 100644 --- a/tests/runtests.bat +++ b/tests/runtests.bat @@ -8,6 +8,7 @@ set OS_NAME=WindowsNT set CHICKEN=..\chicken set CHICKEN_PROFILE=..\chicken-profile +set CHICKEN_REPOSITORY= set ASMFLAGS=-Wa,-w set FAST_OPTIONS=-O5 -d0 -b -disable-interrupts set PATH=%cd%\..;%PATH% @@ -21,7 +22,8 @@ set compile2=..\csc -compiler %CHICKEN% -v -I%TEST_DIR%/.. -L%TEST_DIR%/.. -incl set compile_s=..\csc -s -types %TYPESDB% -ignore-repository -compiler %CHICKEN% -v -I%TEST_DIR%/.. -L%TEST_DIR%/.. -include-path %TEST_DIR%/.. set interpret=..\csi -n -include-path %TEST_DIR%/.. -del /f /q *.exe *.so *.o *.import.* ..\foo.import.* +del /f /q /s *.exe *.so *.o *.import.* ..\foo.import.* test-repository +mkdir test-repository echo ======================================== version tests ... %interpret% -s version-tests.scm @@ -531,6 +533,29 @@ if errorlevel 1 exit /b 1 a.out if errorlevel 1 exit /b 1 +echo ======================================== linking tests ... +%compile% -unit reverser reverser\tags\1.0\reverser.scm -J -c -o reverser.o +%compile% -link reverser linking-tests.scm +if errorlevel 1 exit /b 1 +a.out +if errorlevel 1 exit /b 1 +%compile% -link reverser linking-tests.scm -static +if errorlevel 1 exit /b 1 +a.out +if errorlevel 1 exit /b 1 +set CHICKEN_REPOSITORY=test-repository +mkdir %CHICKEN_REPOSITORY% +move reverser.o %CHICKEN_REPOSITORY% +move reverser.import.scm %CHICKEN_REPOSITORY% +%compile% -link reverser linking-tests.scm +if errorlevel 1 exit /b 1 +a.out +if errorlevel 1 exit /b 1 +%compile% -link reverser linking-tests.scm -static +if errorlevel 1 exit /b 1 +a.out +if errorlevel 1 exit /b 1 + echo ======================================== private repository test ... del /f /s /q tmp mkdir tmp diff --git a/tests/runtests.sh b/tests/runtests.sh index 8d307067..fdf3da9d 100755 --- a/tests/runtests.sh +++ b/tests/runtests.sh @@ -444,6 +444,18 @@ echo "======================================== embedding (3) ..." $compile -e embedded3.c embedded4.scm ./a.out +echo "======================================== linking tests ..." +$compile -unit reverser reverser/tags/1.0/reverser.scm -J -c -o reverser.o +$compile -link reverser linking-tests.scm +./a.out +$compile -link reverser linking-tests.scm -static +./a.out +mv reverser.o reverser.import.scm "$CHICKEN_REPOSITORY" +CHICKEN_REPOSITORY=$CHICKEN_REPOSITORY $compile -link reverser linking-tests.scm +./a.out +CHICKEN_REPOSITORY=$CHICKEN_REPOSITORY $compile -link reverser linking-tests.scm -static +./a.out + echo "======================================== private repository test ..." mkdir -p tmp $compile private-repository-test.scm -private-repository -o tmp/xxxTrap