From 826cc92983a457bcde0de0f888b4c86bfdd7c490 Mon Sep 17 00:00:00 2001 From: Marius Gerbershagen Date: Sun, 8 Aug 2021 10:45:28 +0200 Subject: [PATCH 1/2] cmp: introduce new variables for linker flags Split up the options into additional flags for the linker and additional libraries. Quoting from issue #636: > Here's an example, attempting to link one object file named example.o into an executable named example. Libcrypto here is superfluous and should be removed by --as-needed: ``` LDFLAGS="-Wl,--as-needed" LIBS="-lcrypto" gcc ${LDFLAGS} ${LIBS} example.o -o example # doesn't link libcrypto! gcc example.o ${LDFLAGS} ${LIBS} -o example # doesn't honor --as-needed! gcc ${LDFLAGS} example.o ${LIBS} -o example # works great! ``` > In short, the placement of your -l flags differs from that of all the other linker flags. Since ECL is only providing one big variable ld-flags for all of the linker flags, there's no correct way to pass in options like --as-needed and -l at the same time. Fixes #636. --- CHANGELOG | 8 ++++ src/cmp/cmpdefs.lsp | 13 +++--- src/cmp/cmpglobals.lsp | 18 ++++++-- src/cmp/cmpmain.lsp | 60 ++++++++++++++++++-------- src/cmp/cmppackage.lsp | 4 +- src/compile.lsp.in | 28 ++++++------ src/doc/manual/extensions/building.txi | 18 ++++++-- 7 files changed, 103 insertions(+), 46 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 821b26afe..cd879fa34 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -45,6 +45,14 @@ ** API changes - A new function ~(mp:semaphore-wait semaphore count timeout)~ - Deprecate Functions ~mp:wait-on-semaphore~ and ~mp:try-get-semphore~ +- The variable ~c:*user-ld-flags*~ is deprecated in favor of + ~c:*user-linker-flags*~ for option flags (like ~-Wl,foo~) and + ~c:*user-linker-libs*~ for libraries to link in (like ~-lfoo~). + + The variable ~c:*user-ld-flags*~ is left for backward compatibility and + may be removed in future releases - it may cause option flags to be added + in the wrong place in the commandline when invoking the C compiler + program. * 21.2.1 changes since 20.4.24 ** Announcement diff --git a/src/cmp/cmpdefs.lsp b/src/cmp/cmpdefs.lsp index 7926ed025..839b3b7a9 100644 --- a/src/cmp/cmpdefs.lsp +++ b/src/cmp/cmpdefs.lsp @@ -52,17 +52,16 @@ coprocessor).") (t "~A -I. \"-I~A\" ~A ~:[~*~;~A~] -w -c \"~A\" -o \"~A\"~{ '~A'~}"))) +(defvar *ld-flags* "@LDFLAGS@") #-dlopen -(defvar *ld-flags* "@LDFLAGS@ -lecl @CORE_LIBS@ @FASL_LIBS@ @LIBS@") +(defvar *ld-libs* "-lecl @CORE_LIBS@ @FASL_LIBS@ @LIBS@") #+dlopen -(defvar *ld-flags* #-msvc "@LDFLAGS@ -lecl @FASL_LIBS@ @LIBS@" - #+msvc "@LDFLAGS@ ecl.lib @CLIBS@") +(defvar *ld-libs* #-msvc "-lecl @FASL_LIBS@ @LIBS@" + #+msvc "ecl.lib @CLIBS@") #+dlopen -(defvar *ld-shared-flags* #-msvc "@SHARED_LDFLAGS@ @LDFLAGS@ -lecl @FASL_LIBS@ @LIBS@" - #+msvc "@SHARED_LDFLAGS@ @LDFLAGS@ ecl.lib @CLIBS@") +(defvar *ld-shared-flags* "@SHARED_LDFLAGS@ @LDFLAGS@") #+dlopen -(defvar *ld-bundle-flags* #-msvc "@BUNDLE_LDFLAGS@ @LDFLAGS@ -lecl @FASL_LIBS@ @LIBS@" - #+msvc "@BUNDLE_LDFLAGS@ @LDFLAGS@ ecl.lib @CLIBS@") +(defvar *ld-bundle-flags* "@BUNDLE_LDFLAGS@ @LDFLAGS@") (defvar +shared-library-prefix+ "@SHAREDPREFIX@") (defvar +shared-library-extension+ "@SHAREDEXT@") diff --git a/src/cmp/cmpglobals.lsp b/src/cmp/cmpglobals.lsp index d3861d91e..24c621179 100644 --- a/src/cmp/cmpglobals.lsp +++ b/src/cmp/cmpglobals.lsp @@ -205,9 +205,21 @@ value of *CMP-ENV*.") (defvar *files-to-be-deleted* '()) (defvar *user-ld-flags* '() -"Flags and options to be passed to the linker when building FASL, shared libraries -and standalone programs. It is not required to surround values with quotes or use -slashes before special characters.") +"DEPRECATED Flags and options to be passed to the linker when building FASL, +shared libraries and standalone programs. It is not required to surround values +with quotes or use slashes before special characters.") + +(defvar *user-linker-flags* '() + "Command line flags for additional options (e.g. \"-Wl,foo\" flags) to +be passed to the linker when building FASL, shared libraries and +standalone programs. It is not required to surround values with quotes +or use slashes before special characters.") + +(defvar *user-linker-libs* '() +"Command line flags for additional libraries (e.g. \"-lfoo\" flags) to +be passed to the linker when building FASL, shared libraries and +standalone programs. It is not required to surround values with quotes +or use slashes before special characters.") (defvar *user-cc-flags* '() "Flags and options to be passed to the C compiler when building FASL, shared libraries diff --git a/src/cmp/cmpmain.lsp b/src/cmp/cmpmain.lsp index 41ba81e5a..ec4170e3e 100644 --- a/src/cmp/cmpmain.lsp +++ b/src/cmp/cmpmain.lsp @@ -125,17 +125,28 @@ the environment variable TMPDIR to a different value." template)) (let ((x (string-right-trim '(#\\ #\/) directory-namestring))) (if (zerop (length x)) "/" x))) +(defun get-deprecated-user-ld-flags () + (let ((flags (split-program-options *user-ld-flags*))) + (when flags + (cmwarn "The variable ~s is deprecated, please use ~s and ~s instead." + '*user-ld-flags* '*user-linker-flags* '*user-linker-libs*)) + flags)) + #+msvc (defun linker-cc (o-pathname object-files &key (type :program) - (ld-flags (split-program-options *ld-flags*))) + (ld-flags (split-program-options *ld-flags*)) + (ld-libs (split-program-options *ld-libs*))) (safe-run-program *ld* `(,(concatenate 'string "-Fe" (brief-namestring o-pathname)) - ,@object-files ,@(split-program-options *ld-rpath*) - ,@(split-program-options *user-ld-flags*) + ,@(split-program-options *user-linker-flags*) + ,@object-files ,@ld-flags + ,@(split-program-options *user-linker-libs*) + ,@(get-deprecated-user-ld-flags) + ,@ld-libs ,(if (eq type :program) (concatenate 'string "/IMPLIB:prog" (file-namestring o-pathname) ".lib") "") @@ -147,28 +158,32 @@ the environment variable TMPDIR to a different value." template)) #-msvc (defun linker-cc (o-pathname object-files &key (type :program) - (ld-flags (split-program-options *ld-flags*))) + (ld-flags (split-program-options *ld-flags*)) + (ld-libs (split-program-options *ld-libs*))) (declare (ignore type)) (safe-run-program *ld* `("-o" ,(brief-namestring o-pathname) ,(concatenate 'string "-L" (fix-for-mingw (ecl-library-directory))) + ,@(split-program-options *user-linker-flags*) + ,@ld-flags ,@object-files ,@(and *ld-rpath* (list *ld-rpath*)) - ,@(split-program-options *user-ld-flags*) - ,@ld-flags))) + ,@(split-program-options *user-linker-libs*) + ,@(get-deprecated-user-ld-flags) + ,@ld-libs))) -(defun linker-ar (output-name o-name ld-flags) +(defun linker-ar (output-name o-name ld-libs) #-msvc (static-lib-ar (namestring output-name) - (list* (brief-namestring o-name) ld-flags)) + (list* (brief-namestring o-name) ld-libs)) #+msvc (unwind-protect (progn (with-open-file (f "static_lib.tmp" :direction :output :if-does-not-exist :create :if-exists :supersede) (format f "/OUT:~A ~A ~{~&\"~A\"~}" - output-name o-name ld-flags)) + output-name o-name ld-libs)) (safe-run-program "link" '("-lib" "-nologo" "@static_lib.tmp"))) (when (probe-file "static_lib.tmp") (cmp-delete-file "static_lib.tmp")))) @@ -182,7 +197,8 @@ the environment variable TMPDIR to a different value." template)) #+dlopen (defun shared-cc (o-pathname object-files) - (let ((ld-flags (split-program-options *ld-shared-flags*))) + (let ((ld-flags (split-program-options *ld-shared-flags*)) + (ld-libs (split-program-options *ld-libs*))) #+msvc (setf ld-flags (let ((implib (brief-namestring @@ -196,11 +212,13 @@ the environment variable TMPDIR to a different value." template)) (concatenate 'string "/IMPLIB:" implib))))) #+mingw32 (setf ld-flags (list* "-shared" ld-flags)) - (linker-cc o-pathname object-files :type :dll :ld-flags ld-flags))) + (linker-cc o-pathname object-files :type :dll + :ld-flags ld-flags :ld-libs ld-libs))) #+dlopen (defun bundle-cc (o-pathname init-name object-files) - (let ((ld-flags (split-program-options *ld-bundle-flags*))) + (let ((ld-flags (split-program-options *ld-bundle-flags*)) + (ld-libs (split-program-options *ld-libs*))) #+msvc (setf ld-flags (let ((implib (brief-namestring @@ -217,7 +235,8 @@ the environment variable TMPDIR to a different value." template)) (concatenate 'string "/IMPLIB:" implib))))) #+mingw32 (setf ld-flags (list* "-shared" "-Wl,--export-all-symbols" ld-flags)) - (linker-cc o-pathname object-files :type :fasl :ld-flags ld-flags))) + (linker-cc o-pathname object-files :type :fasl + :ld-flags ld-flags :ld-libs ld-libs))) (defconstant +lisp-program-header+ " #include @@ -417,7 +436,7 @@ filesystem or in the database of ASDF modules." (defun builder (target output-name &key - lisp-files ld-flags + lisp-files ld-flags ld-libs (init-name nil) (main-name nil) (prologue-code "") @@ -517,7 +536,7 @@ output = si_safe_eval(2, ecl_read_from_cstring(lisp_code), ECL_NIL); (let* ((init-fn (guess-init-name path kind)) (flags (guess-ld-flags path))) ;; We should give a warning that we cannot link this module in - (when flags (push flags ld-flags)) + (when flags (push flags ld-libs)) (when init-fn (push (list init-fn path) submodules))))) (setq c-file (open c-name :direction :output :external-format :default)) @@ -537,7 +556,8 @@ output = si_safe_eval(2, ecl_read_from_cstring(lisp_code), ECL_NIL); prologue-code init-name epilogue-code) (close c-file) (compiler-cc c-name o-name) - (linker-cc output-name (list* (namestring o-name) ld-flags))) + (linker-cc output-name (append ld-flags (list (namestring o-name)) + ld-libs))) (:static-library (format c-file +lisp-program-init+ init-name init-tag prologue-code submodules epilogue-code) @@ -548,7 +568,7 @@ output = si_safe_eval(2, ecl_read_from_cstring(lisp_code), ECL_NIL); (close c-file) (compiler-cc c-name o-name) (when (probe-file output-name) (delete-file output-name)) - (linker-ar output-name o-name ld-flags)) + (linker-ar output-name o-name ld-libs)) #+dlopen (:shared-library (format c-file +lisp-program-init+ @@ -559,7 +579,8 @@ output = si_safe_eval(2, ecl_read_from_cstring(lisp_code), ECL_NIL); main-name prologue-code init-name epilogue-code) (close c-file) (compiler-cc c-name o-name) - (shared-cc output-name (list* o-name ld-flags))) + (shared-cc output-name (append ld-flags (list o-name) + ld-libs))) #+dlopen (:fasl (format c-file +lisp-program-init+ init-name init-tag prologue-code @@ -568,7 +589,8 @@ output = si_safe_eval(2, ecl_read_from_cstring(lisp_code), ECL_NIL); ;(format c-file +lisp-init-wrapper+ wrap-name init-name) (close c-file) (compiler-cc c-name o-name) - (bundle-cc output-name init-name (list* o-name ld-flags)))) + (bundle-cc output-name init-name (append ld-flags (list o-name) + ld-libs)))) (mapc 'cmp-delete-file tmp-names) (cmp-delete-file c-name) (cmp-delete-file o-name) diff --git a/src/cmp/cmppackage.lsp b/src/cmp/cmppackage.lsp index 9ea3fbcc3..0c4737ff0 100644 --- a/src/cmp/cmppackage.lsp +++ b/src/cmp/cmppackage.lsp @@ -27,7 +27,9 @@ #:*cc* #:*cc-optimize* #:*user-cc-flags* - #:*user-ld-flags* + #:*user-ld-flags* ; deprecated + #:*user-linker-flags* + #:*user-linker-libs* #:*suppress-compiler-messages* ;; Build targets. BUILD-ECL is not defined, preasumbly it was meant ;; for cross compilation. diff --git a/src/compile.lsp.in b/src/compile.lsp.in index b5d9c5ed7..bbb102d4d 100755 --- a/src/compile.lsp.in +++ b/src/compile.lsp.in @@ -86,24 +86,24 @@ #+msvc "@CFLAGS@ @ECL_CFLAGS@" c::*ecl-include-directory* "@true_builddir@/" c::*ecl-library-directory* "@true_builddir@/") -#-:wants-dlopen -(setf c::*ld-flags* - "@LDFLAGS@ @LIBPREFIX@ecl.@LIBEXT@ @CORE_LIBS@ @FASL_LIBS@ @LIBS@") +(setf c::*ld-flags* "@LDFLAGS@") +#-:wants-dlopen +(setf c::*ld-libs* "@LIBPREFIX@ecl.@LIBEXT@ @CORE_LIBS@ @FASL_LIBS@ @LIBS@") #+(and :wants-dlopen (not nonstop)) -(setf c::*ld-flags* - "@LDFLAGS@ @SHAREDPREFIX@ecl.@SHAREDEXT@ @LIBS@" +(setf c::*ld-libs* + "@SHAREDPREFIX@ecl.@SHAREDEXT@ @LIBS@" c::*ld-shared-flags* - "@SHARED_LDFLAGS@ @LDFLAGS@ @SHAREDPREFIX@ecl.@SHAREDEXT@ @FASL_LIBS@ @LIBS@" + "@SHARED_LDFLAGS@ @LDFLAGS@" c::*ld-bundle-flags* - "@BUNDLE_LDFLAGS@ @LDFLAGS@ @SHAREDPREFIX@ecl.@SHAREDEXT@ @FASL_LIBS@ @LIBS@") + "@BUNDLE_LDFLAGS@ @LDFLAGS@") ;;; FIXME: The nonstop platform does not support soname #+(and :wants-dlopen nonstop) -(setf c::*ld-flags* - "@LDFLAGS@ -Wld=-l@SHAREDPREFIX@ecl.@SHAREDEXT@ @LIBS@" +(setf c::*ld-libs* + "-Wld=-l@SHAREDPREFIX@ecl.@SHAREDEXT@ @LIBS@" c::*ld-shared-flags* - "@SHARED_LDFLAGS@ @LDFLAGS@ -Wld=-l@SHAREDPREFIX@ecl.@SHAREDEXT@ @FASL_LIBS@ @LIBS@" + "@SHARED_LDFLAGS@ @LDFLAGS@ -Wld=-l@SHAREDPREFIX@ecl.@SHAREDEXT@" c::*ld-bundle-flags* - "@BUNDLE_LDFLAGS@ @LDFLAGS@ -Wld=-l@SHAREDPREFIX@ecl.@SHAREDEXT@ @FASL_LIBS@ @LIBS@") + "@BUNDLE_LDFLAGS@ @LDFLAGS@ -Wld=-l@SHAREDPREFIX@ecl.@SHAREDEXT@") ;;; ;;; * Avoid name clashes with user supplied code. @@ -162,8 +162,10 @@ ;;; ;;; We do not need the -rpath flag for the library, nor -lecl. ;;; -(let* ((c::*ld-shared-flags* #-msvc "@SHARED_LDFLAGS@ @LDFLAGS@ @SONAME_LDFLAGS@ @CORE_LIBS@ @FASL_LIBS@ @LIBS@" - #+msvc "@SHARED_LDFLAGS@ @LDFLAGS@ @STATICLIBS@ @CLIBS@") +(let* ((c::*ld-shared-flags* #-msvc "@SHARED_LDFLAGS@ @LDFLAGS@ @SONAME_LDFLAGS@" + #+msvc "@SHARED_LDFLAGS@ @LDFLAGS@") + (c::*ld-libs* #-msvc "@CORE_LIBS@ @FASL_LIBS@ @LIBS@" + #+msvc "@STATICLIBS@ @CLIBS@") (c::*cc-flags* (concatenate 'string "-DECL_API -I@true_builddir@/c " c::*cc-flags*)) (extra-args nil)) #+(or mingw32 cygwin) diff --git a/src/doc/manual/extensions/building.txi b/src/doc/manual/extensions/building.txi index 48dc13530..628896941 100644 --- a/src/doc/manual/extensions/building.txi +++ b/src/doc/manual/extensions/building.txi @@ -543,15 +543,27 @@ Flags and options to be passed to the C compiler when building FASL, shared libraries and standalone programs. @end deftypevar -@deftypevar string {c:*user-ld-flags*} -Flags and options to be passed to the linker when building FASL, -shared libraries and standalone programs. +@deftypevar string {c:*user-linker-flags*} +Flags for options (e.g. @code{-Wl,foo} flags, usually in the +@code{$LDFLAGS} variable in autoconf) to be passed to the linker when +building FASL, shared libraries and standalone programs. +@end deftypevar + +@deftypevar string {c:*user-linker-libs*} +Flags for libraries (e.g. @code{-lfoo} flags, usually in the +@code{$LIBS} variable in autoconf) to be passed to the linker when +building FASL, shared libraries and standalone programs. @end deftypevar @deftypevar string {c:*cc-optimize*} Optimize options to be passed to the C compiler. @end deftypevar +@deftypevar string {c:*user-ld-flags*} +@strong{DEPRECATED} Flags and options to be passed to the linker when +building FASL, shared libraries and standalone programs. +@end deftypevar + @subsubsection Compiler & Linker programs @deftypevar string {c::*cc*} From 6d191760b3d77e21fe667274eb25303e0a385b5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Kochma=C5=84ski?= Date: Thu, 8 Sep 2022 09:02:42 +0200 Subject: [PATCH 2/2] cosmetic: cmp: rename a function guess-ld-flags to guess-ld-libs ... to better reflect what it returns. --- src/cmp/cmpmain.lsp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/cmp/cmpmain.lsp b/src/cmp/cmpmain.lsp index ec4170e3e..a1fc18c55 100644 --- a/src/cmp/cmpmain.lsp +++ b/src/cmp/cmpmain.lsp @@ -389,7 +389,7 @@ or a loadable module." pathname) :object)))) -(defun guess-ld-flags (pathname &key (kind (guess-kind pathname))) +(defun guess-ld-libs (pathname &key (kind (guess-kind pathname))) "Given a file name, return the compiler command line argument to link this file in." (case kind ((:object :c) @@ -532,11 +532,11 @@ output = si_safe_eval(2, ecl_read_from_cstring(lisp_code), ECL_NIL); '(:shared-library :static-library)) :object :c)) (error "C::BUILDER does not accept a file ~s of kind ~s for target ~s" item kind target)) - - (let* ((init-fn (guess-init-name path kind)) - (flags (guess-ld-flags path))) + (let ((init-fn (guess-init-name path kind)) + (guessed-libs (guess-ld-libs path))) ;; We should give a warning that we cannot link this module in - (when flags (push flags ld-libs)) + (when guessed-libs + (push guessed-libs ld-libs)) (when init-fn (push (list init-fn path) submodules))))) (setq c-file (open c-name :direction :output :external-format :default))