Commit 4f6fcf0c authored by Marius Gerbershagen's avatar Marius Gerbershagen
Browse files

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<foo> 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<foo> at the same
  time.

Fixes #636.
parent 43be4f6d
......@@ -52,17 +52,21 @@ coprocessor).")
(t
"~A -I. \"-I~A\" ~A ~:[~*~;~A~] -w -c \"~A\" -o \"~A\"~{ '~A'~}")))
(defvar *ld-flags* "") ; deprecated, use *ld-option-flags* and *ld-library-flags* instead
(defvar *ld-option-flags* "@LDFLAGS@")
#-dlopen
(defvar *ld-flags* "@LDFLAGS@ -lecl @CORE_LIBS@ @FASL_LIBS@ @LIBS@")
(defvar *ld-library-flags* "-lecl @CORE_LIBS@ @FASL_LIBS@ @LIBS@")
#+dlopen
(defvar *ld-flags* #-msvc "@LDFLAGS@ -lecl @FASL_LIBS@ @LIBS@"
#+msvc "@LDFLAGS@ ecl.lib @CLIBS@")
(defvar *ld-library-flags* #-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* "") ; deprecated, use *ld-shared-option-flags* and *ld-library-flags* instead
#+dlopen
(defvar *ld-bundle-flags* #-msvc "@BUNDLE_LDFLAGS@ @LDFLAGS@ -lecl @FASL_LIBS@ @LIBS@"
#+msvc "@BUNDLE_LDFLAGS@ @LDFLAGS@ ecl.lib @CLIBS@")
(defvar *ld-bundle-flags* "") ; deprecated, use *ld-bundle-option-flags* and *ld-library-flags* instead
#+dlopen
(defvar *ld-shared-option-flags* "@SHARED_LDFLAGS@ @LDFLAGS@")
#+dlopen
(defvar *ld-bundle-option-flags* "@BUNDLE_LDFLAGS@ @LDFLAGS@")
(defvar +shared-library-prefix+ "@SHAREDPREFIX@")
(defvar +shared-library-extension+ "@SHAREDEXT@")
......
......@@ -204,8 +204,22 @@ value of *CMP-ENV*.")
(defvar *delete-files* t)
(defvar *files-to-be-deleted* '())
(defvar *user-ld-option-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-ld-library-flags* '()
"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-ld-flags* '()
"Flags and options to be passed to the linker when building FASL, shared libraries
"DEPRECATED: Use *user-ld-option-flags* and *user-ld-library-flags* instead.
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.")
......
......@@ -125,17 +125,36 @@ the environment variable TMPDIR to a different value." template))
(let ((x (string-right-trim '(#\\ #\/) directory-namestring)))
(if (zerop (length x)) "/" x)))
(defun append-deprecated-ld-flags (ld-option-flags ld-library-flags)
(when-let ((ld-flags (split-program-options *ld-flags*)))
(cmpwarn "The variable c::*ld-flags* is deprecated. Please use c::*ld-option-flags* and c::*ld-library-flags* instead.")
;; To preserve compatibility with older releases, whenever
;; ld-flags is non-empty this variable specifies the _whole_ set
;; of linker flags, taking precedence over both ld-option-flags
;; and ld-library-flags.
(setf ld-option-flags nil
ld-library-flags ld-flags))
(when-let ((user-ld-flags (split-program-options *user-ld-flags*)))
(cmpwarn "The variable c::*user-ld-flags* is deprecated. Please use c::*user-ld-option-flags* and c::*user-ld-library-flags* instead.")
(setf ld-library-flags (nconc user-ld-flags ld-library-flags)))
(values ld-option-flags ld-library-flags))
#+msvc
(defun linker-cc (o-pathname object-files &key
(type :program)
(ld-flags (split-program-options *ld-flags*)))
(ld-option-flags (split-program-options *ld-option-flags*))
(ld-library-flags (split-program-options *ld-library-flags*)))
(setf (values ld-option-flags ld-library-flags)
(append-deprecated-ld-flags ld-option-flags ld-library-flags))
(safe-run-program
*ld*
`(,(concatenate 'string "-Fe" (brief-namestring o-pathname))
,@object-files
,@(split-program-options *ld-rpath*)
,@(split-program-options *user-ld-flags*)
,@ld-flags
,@(split-program-options *user-ld-option-flags*)
,@ld-option-flags
,@(split-program-options *user-ld-library-flags*)
,@ld-library-flags
,(if (eq type :program)
(concatenate 'string "/IMPLIB:prog" (file-namestring o-pathname) ".lib")
"")
......@@ -147,28 +166,33 @@ 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-option-flags (split-program-options *ld-option-flags*))
(ld-library-flags (split-program-options *ld-library-flags*)))
(declare (ignore type))
(setf (values ld-option-flags ld-library-flags)
(append-deprecated-ld-flags ld-option-flags ld-library-flags))
(safe-run-program
*ld*
`("-o" ,(brief-namestring o-pathname)
,(concatenate 'string "-L" (fix-for-mingw (ecl-library-directory)))
,@(split-program-options *user-ld-option-flags*)
,@ld-option-flags
,@object-files
,@(and *ld-rpath* (list *ld-rpath*))
,@(split-program-options *user-ld-flags*)
,@ld-flags)))
,@(split-program-options *user-ld-library-flags*)
,@ld-library-flags)))
(defun linker-ar (output-name o-name ld-flags)
(defun linker-ar (output-name o-name ld-library-flags)
#-msvc
(static-lib-ar (namestring output-name)
(list* (brief-namestring o-name) ld-flags))
(list* (brief-namestring o-name) ld-library-flags))
#+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-library-flags))
(safe-run-program "link" '("-lib" "-nologo" "@static_lib.tmp")))
(when (probe-file "static_lib.tmp")
(cmp-delete-file "static_lib.tmp"))))
......@@ -182,33 +206,44 @@ 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-option-flags (split-program-options *ld-shared-option-flags*))
(ld-library-flags (split-program-options *ld-library-flags*)))
(when-let ((ld-flags (split-program-options *ld-shared-flags*)))
(cmpwarn "The variable c::*ld-shared-flags* is deprecated. Please use c::*ld-shared-option-flags* to specify linker options for shared libraries and c::*ld-library-flags* to specify additional libraries to link in.")
(setf ld-option-flags nil
ld-library-flags ld-flags))
#+msvc
(setf ld-flags
(setf ld-option-flags
(let ((implib (si::coerce-to-filename
(compile-file-pathname o-pathname :type :lib))))
;; MSVC linker options are added at the end, after the
;; /link flag, because they are not processed by the
;; compiler, but by the linker
(append ld-flags
(append ld-option-flags
(list (concatenate 'string "/LIBPATH:"
(ecl-library-directory))
(concatenate 'string "/IMPLIB:" implib)))))
#+mingw32
(setf ld-flags (list* "-shared" ld-flags))
(linker-cc o-pathname object-files :type :dll :ld-flags ld-flags)))
(setf ld-option-flags (list* "-shared" ld-option-flags))
(linker-cc o-pathname object-files :type :dll
:ld-option-flags ld-option-flags :ld-library-flags ld-library-flags)))
#+dlopen
(defun bundle-cc (o-pathname init-name object-files)
(let ((ld-flags (split-program-options *ld-bundle-flags*)))
(let ((ld-option-flags (split-program-options *ld-bundle-option-flags*))
(ld-library-flags (split-program-options *ld-library-flags*)))
(when-let ((ld-flags (split-program-options *ld-bundle-flags*)))
(cmpwarn "The variable c::*ld-bundle-flags* is deprecated. Please use c::*ld-bundle-option-flags* to specify linker options for bundles and c::*ld-library-flags* to specify additional libraries to link in.")
(setf ld-option-flags nil
ld-library-flags ld-flags))
#+msvc
(setf ld-flags
(setf ld-option-flags
(let ((implib (si::coerce-to-filename
(compile-file-pathname o-pathname :type :import-library))))
;; MSVC linker options are added at the end, after the
;; /link flag, because they are not processed by the
;; compiler, but by the linker
(append ld-flags
(append ld-option-flags
(list
;; Not needed because we use ECL_DLLEXPORT
;; (concatenate 'string "/EXPORT:" init-name)
......@@ -216,8 +251,9 @@ the environment variable TMPDIR to a different value." template))
(ecl-library-directory))
(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)))
(setf ld-option-flags (list* "-shared" "-Wl,--export-all-symbols" ld-option-flags))
(linker-cc o-pathname object-files :type :fasl
:ld-option-flags ld-option-flags :ld-library-flags ld-library-flags)))
(defconstant +lisp-program-header+ "
#include <ecl/ecl.h>
......@@ -417,7 +453,7 @@ filesystem or in the database of ASDF modules."
(defun builder (target output-name
&key
lisp-files ld-flags
lisp-files ld-flags ld-option-flags ld-library-flags
(init-name nil)
(main-name nil)
(prologue-code "")
......@@ -432,6 +468,11 @@ filesystem or in the database of ASDF modules."
output-name))
;; wrap-name is the init function name defined by a programmer
(wrap-name init-name))
;; warn for deprecated arguments
(when ld-flags
(cmpwarn "The :LD-FLAGS argument to the C::BUILDER function is deprecated. Please use the :LD-OPTION-FLAGS argument to specify linker options and the :LD-LIBRARY-FLAGS arguments to add additional libraries to link in.")
(setf ld-library-flags (append ld-library-flags ld-flags)))
;; init-name should always be unique
(setf init-name (compute-init-name output-name :kind target))
(cond ((null wrap-name) nil)
......@@ -517,7 +558,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-library-flags))
(when init-fn
(push (list init-fn path) submodules)))))
(setq c-file (open c-name :direction :output :external-format :default))
......@@ -537,7 +578,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-option-flags (list (namestring o-name))
ld-library-flags)))
(:static-library
(format c-file +lisp-program-init+
init-name init-tag prologue-code submodules epilogue-code)
......@@ -548,7 +590,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-library-flags))
#+dlopen
(:shared-library
(format c-file +lisp-program-init+
......@@ -559,7 +601,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-option-flags (list o-name)
ld-library-flags)))
#+dlopen
(:fasl
(format c-file +lisp-program-init+ init-name init-tag prologue-code
......@@ -568,7 +611,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-option-flags (list o-name)
ld-library-flags))))
(mapc 'cmp-delete-file tmp-names)
(cmp-delete-file c-name)
(cmp-delete-file o-name)
......
......@@ -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-option-flags* "@LDFLAGS@")
#-:wants-dlopen
(setf c::*ld-library-flags* "@LIBPREFIX@ecl.@LIBEXT@ @CORE_LIBS@ @FASL_LIBS@ @LIBS@")
#+(and :wants-dlopen (not nonstop))
(setf c::*ld-flags*
"@LDFLAGS@ @SHAREDPREFIX@ecl.@SHAREDEXT@ @LIBS@"
c::*ld-shared-flags*
"@SHARED_LDFLAGS@ @LDFLAGS@ @SHAREDPREFIX@ecl.@SHAREDEXT@ @FASL_LIBS@ @LIBS@"
c::*ld-bundle-flags*
"@BUNDLE_LDFLAGS@ @LDFLAGS@ @SHAREDPREFIX@ecl.@SHAREDEXT@ @FASL_LIBS@ @LIBS@")
(setf c::*ld-library-flags*
"@SHAREDPREFIX@ecl.@SHAREDEXT@ @LIBS@"
c::*ld-shared-option-flags*
"@SHARED_LDFLAGS@ @LDFLAGS@"
c::*ld-bundle-option-flags*
"@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@"
c::*ld-shared-flags*
"@SHARED_LDFLAGS@ @LDFLAGS@ -Wld=-l@SHAREDPREFIX@ecl.@SHAREDEXT@ @FASL_LIBS@ @LIBS@"
c::*ld-bundle-flags*
"@BUNDLE_LDFLAGS@ @LDFLAGS@ -Wld=-l@SHAREDPREFIX@ecl.@SHAREDEXT@ @FASL_LIBS@ @LIBS@")
(setf c::*ld-library-flags*
"-Wld=-l@SHAREDPREFIX@ecl.@SHAREDEXT@ @LIBS@"
c::*ld-shared-option-flags*
"@SHARED_LDFLAGS@ @LDFLAGS@ -Wld=-l@SHAREDPREFIX@ecl.@SHAREDEXT@"
c::*ld-bundle-option-flags*
"@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-option-flags* #-msvc "@SHARED_LDFLAGS@ @LDFLAGS@ @SONAME_LDFLAGS@"
#+msvc "@SHARED_LDFLAGS@ @LDFLAGS@")
(c::*ld-library-flags* #-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)
......@@ -362,7 +364,7 @@
#-(or cross stage1 msvc) "ecl2"
:epilogue-code '@ECL_INIT_FORM@
:lisp-files *module-symbols*
:ld-flags
:ld-option-flags
(concatenate 'list #-msvc '("-L./") #+windows '("ecl.res" #+msvc "/F 10485760")))
(with-open-file (modules-list #P"build:MODULES" :direction :output
......
......@@ -543,9 +543,14 @@ 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-ld-option-flags*}
Flags for options (e.g. @code{-Wl,foo} flags) to be passed to the linker
when building FASL, shared libraries and standalone programs.
@end deftypevar
@deftypevar string {c:*user-ld-library-flags*}
Flags for libraries (e.g. @code{-lfoo} flags) to be passed to the linker
when building FASL, shared libraries and standalone programs.
@end deftypevar
@deftypevar string {c:*cc-optimize*}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment