[PATCH 2/2] libtool: factor out the dll .def file test and improve it

Peter Rosin <[email protected]>
Newsgroups gmane.comp.gnu.libtool.patches
Message-ID <[email protected]>
Resolves bug#13414. Problem reported by Erik van Pienbroek
and Martin Doucha.

build-aux/ltmain.in (func_mode_link): Factor out the test if a
given symbol file is a module-definition (.def) file into...
(func_dll_def_p): ...this function, which also improves the check.
m4/libtool.m4 (_LT_LINKER_SHLIBS, _LT_LANG_CXX_CONFIG)
<cygwin, mingw, pw32, cegcc>: Similarly, factor out the test if
a given symbol file is a module-definition (.def) file into...
(_LT_DLL_DEF_P): ...this macro, which also improves the check.
tests/export-def.at: New test.
Makefile.am (TESTSUITE_AT): Add above test.
NEWS: Update.
THANKS: Update.

Signed-off-by: Peter Rosin <[email protected]>

# Conflicts:
#
# 	m4/libtool.m4
---
 Makefile.am         |    1 +
 NEWS                |    3 +
 THANKS              |    2 +
 build-aux/ltmain.in |   19 +++++++-
 m4/libtool.m4       |   31 ++++++++---
 tests/export-def.at |  139 +++++++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 186 insertions(+), 9 deletions(-)
 create mode 100755 tests/export-def.at

diff --git a/Makefile.am b/Makefile.am
index a3e3c7d..e5f3805 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -627,6 +627,7 @@ TESTSUITE_AT	= tests/testsuite.at \
 		  tests/runpath-in-lalib.at \
 		  tests/static.at \
 		  tests/export.at \
+		  tests/export-def.at \
 		  tests/search-path.at \
 		  tests/indirect_deps.at \
 		  tests/archive-in-archive.at \
diff --git a/NEWS b/NEWS
index c202c43..514768b 100644
--- a/NEWS
+++ b/NEWS
@@ -66,6 +66,9 @@ NEWS - list of user-visible changes between releases of GNU Libtool
     the Microsoft Visual C/C++ linker via the -export-symbols argument to
     the libtool script, thus matching how .def files are handled when
     using GNU tools.
+  - Recognize more variants (e.g. those starting with a LIBRARY statement)
+    of module-definitions (.def) files when using them instead of a raw
+    list of symbols to export.
 
 ** Important incompatible changes:
 
diff --git a/THANKS b/THANKS
index d4c1f1b..92e6dff 100644
--- a/THANKS
+++ b/THANKS
@@ -98,6 +98,7 @@
   Edouard G. Parmelan		[email protected]
   Erez Zadok			[email protected]
   Eric Estievenart		[email protected]
+  Erik van Pienbroek		[email protected]
   Ethan Mallove			[email protected]
   Frank Ch. Eigler		[email protected]
   Fred Cox			[email protected]
@@ -140,6 +141,7 @@
   Marcel Loose			[email protected]
   Mark Kettenis			[email protected]
   Markus Duft			[email protected]
+  Martin Doucha			[email protected]
   Matthijs Kooijman		[email protected]
   Micheal E. Faenza		[email protected]
   Michael Haubenwallner		[email protected]
diff --git a/build-aux/ltmain.in b/build-aux/ltmain.in
index eb224e3..f0168da 100644
--- a/build-aux/ltmain.in
+++ b/build-aux/ltmain.in
@@ -1316,6 +1316,23 @@ func_convert_path_nix_to_cygwin ()
 # end func_convert_path_nix_to_cygwin
 
 
+# func_dll_def_p FILE
+# True iff FILE is a Windows DLL '.def' file.
+# Keep in sync with _LT_DLL_DEF_P in libtool.m4
+func_dll_def_p ()
+{
+  $debug_cmd
+
+  func_dll_def_p_tmp=`$SED -n \
+    -e 's/^[ 	]*//' \
+    -e '/^\(;.*\)*$/d' \
+    -e 's/^\(EXPORTS\|LIBRARY\)\([ 	].*\)*$/DEF/p' \
+    -e q \
+    "$1"`
+  test DEF = "$func_dll_def_p_tmp"
+}
+
+
 # func_mode_compile arg...
 func_mode_compile ()
 {
@@ -7572,7 +7589,7 @@ EOF
 	cygwin* | mingw* | cegcc*)
 	  if test -n "$export_symbols" && test -z "$export_symbols_regex"; then
 	    # exporting using user supplied symfile
-	    if test EXPORTS != "`$SED 1q $export_symbols`"; then
+	    if ! func_dll_def_p "$export_symbols"; then
 	      # and it's NOT already a .def file. Must figure out
 	      # which of the given symbols are data symbols and tag
 	      # them as such. So, trigger use of export_symbols_cmds.
diff --git a/m4/libtool.m4 b/m4/libtool.m4
index 4bc9e98..0a6c334 100644
--- a/m4/libtool.m4
+++ b/m4/libtool.m4
@@ -3530,6 +3530,21 @@ _LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl
 ])# _LT_PATH_MANIFEST_TOOL
 
 
+# _LT_DLL_DEF_P([FILE])
+# ---------------------
+# True iff FILE is a Windows DLL '.def' file.
+# Keep in sync with func_dll_def_p in the libtool script
+AC_DEFUN([_LT_DLL_DEF_P],
+[dnl
+  test DEF = "`$SED -n dnl
+    -e '\''s/^[[ 	]]*//'\'' dnl Strip leading whitespace
+    -e '\''/^\(;.*\)*$/d'\'' dnl      Delete empty lines and comments
+    -e '\''s/^\(EXPORTS\|LIBRARY\)\([[ 	]].*\)*$/DEF/p'\'' dnl
+    -e q dnl                          Only consider the first "real" line
+    $1`" dnl
+])# _LT_DLL_DEF_P
+
+
 # LT_LIB_M
 # --------
 # check for math library
@@ -4782,9 +4797,9 @@ _LT_EOF
 
       if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
         _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
-	# If the export-symbols file already is a .def file (1st line
-	# is EXPORTS), use it as is; otherwise, prepend...
-	_LT_TAGVAR(archive_expsym_cmds, $1)='if test EXPORTS = "`$SED 1q $export_symbols`"; then
+	# If the export-symbols file already is a .def file, use it as
+	# is; otherwise, prepend EXPORTS...
+	_LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then
           cp $export_symbols $output_objdir/$soname.def;
         else
           echo EXPORTS > $output_objdir/$soname.def;
@@ -5162,7 +5177,7 @@ _LT_EOF
 	shrext_cmds=.dll
 	# FIXME: Setting linknames here is a bad hack.
 	_LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames='
-	_LT_TAGVAR(archive_expsym_cmds, $1)='if test EXPORTS = "`$SED 1q $export_symbols`"; then
+	_LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then
             cp "$export_symbols" "$output_objdir/$soname.def";
             echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp";
           else
@@ -6154,7 +6169,7 @@ if test yes != "$_lt_caught_CXX_error"; then
 	  shrext_cmds=.dll
 	  # FIXME: Setting linknames here is a bad hack.
 	  _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames='
-	  _LT_TAGVAR(archive_expsym_cmds, $1)='if test EXPORTS = "`$SED 1q $export_symbols`"; then
+	  _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then
               cp "$export_symbols" "$output_objdir/$soname.def";
               echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp";
             else
@@ -6194,9 +6209,9 @@ if test yes != "$_lt_caught_CXX_error"; then
 
 	  if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
 	    _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
-	    # If the export-symbols file already is a .def file (1st line
-	    # is EXPORTS), use it as is; otherwise, prepend...
-	    _LT_TAGVAR(archive_expsym_cmds, $1)='if test EXPORTS = "`$SED 1q $export_symbols`"; then
+	    # If the export-symbols file already is a .def file, use it as
+	    # is; otherwise, prepend EXPORTS...
+	    _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then
               cp $export_symbols $output_objdir/$soname.def;
             else
               echo EXPORTS > $output_objdir/$soname.def;
diff --git a/tests/export-def.at b/tests/export-def.at
new file mode 100755
index 0000000..b8dfa55
--- /dev/null
+++ b/tests/export-def.at
@@ -0,0 +1,139 @@
+# export-def.at -- test module-definition files              -*- Autotest -*-
+
+#   Copyright (C) 2007-2008, 2011-2013 Free Software Foundation, Inc.
+#   Written by Peter Rosin, 2013
+#
+#   This file is part of GNU Libtool.
+#
+# GNU Libtool is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# GNU Libtool is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Libtool; see the file COPYING.  If not, a copy
+# can be downloaded from  http://www.gnu.org/licenses/gpl.html,
+# or obtained by writing to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+####
+
+AT_SETUP([export from a DLL with a .def file])
+AT_KEYWORDS([libtool])
+
+AT_CHECK([$LIBTOOL --features | grep 'disable shared libraries' && (exit 77)],
+	 [1], [ignore])
+eval `$LIBTOOL --config | $EGREP '^(shrext_cmds|libname_spec|soname_spec)='`
+
+eval shared_ext=\"$shrext_cmds\"
+
+# skip if not building a .dll
+AT_CHECK([test .dll = "$shared_ext" || (exit 77)])
+
+LDFLAGS="$LDFLAGS -no-undefined"
+libdir=`pwd`/inst/lib
+mkdir inst inst/lib
+
+AT_DATA([a.c],
+[[/* a */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int v1 = -1;
+int v2 (void) { return -2; }
+
+#ifdef __cplusplus
+}
+#endif
+]])
+
+AT_DATA([syms],
+[[v1
+v2
+]])
+
+AT_DATA([def1],
+[[EXPORTS
+v1 DATA
+v2
+]])
+
+AT_DATA([def2],
+[[; Def file
+    ; with some very important comments
+EXPORTS
+v1 DATA
+v2
+]])
+
+AT_DATA([def3],
+[[
+   EXPORTS v1 DATA
+   v2
+]])
+
+AT_DATA([def4],
+[[	LIBRARY %soname%
+EXPORTS
+v1 DATA
+v2
+]])
+
+AT_DATA([main.c],
+[[
+/* w32 fun.  With GCC, you can have auto-import, which will work for
+ * functions and non-const variables.  With MSVC, you have to explicitly
+ * import all variables.
+ *
+ * For users, it's best to realize that they should not provide any
+ * non-function API at all.
+ */
+#if defined LIBA_DLL_IMPORT
+#  if defined _WIN32 && defined _MSC_VER
+#    define LIBA_SCOPE_VAR extern __declspec(dllimport)
+#  endif
+#endif
+#if !defined LIBA_SCOPE_VAR
+#  define LIBA_SCOPE_VAR extern
+#endif
+#ifdef __cplusplus
+extern "C" {
+#endif
+LIBA_SCOPE_VAR int v1;
+extern int v2(void);
+#ifdef __cplusplus
+}
+#endif
+
+int main (void)
+{
+  return v1 + v2() + 3;
+}
+]])
+
+name=a
+eval libname=\"$libname_spec\"
+major=0
+versuffix=-$major
+eval soname=\"$soname_spec\"
+
+AT_CHECK([$LIBTOOL --mode=compile $CC $CPPFLAGS $CFLAGS -c a.c],[0],[ignore],[ignore])
+AT_CHECK([$CC $CPPFLAGS -DLIBA_DLL_IMPORT $CFLAGS -c main.c],[0],[ignore],[ignore])
+
+for exportsyms in syms def1 def2 def3 def4
+do
+  $SED "s/%soname%/$soname/" -i $exportsyms
+
+  LT_AT_CHECK([eval '$LIBTOOL --mode=link $CC $CFLAGS $LDFLAGS -o liba.la a.lo \
+	       -rpath $libdir' -export-symbols $exportsyms], [], [ignore], [ignore])
+  AT_CHECK([$LIBTOOL --mode=link $CC $CFLAGS $LDFLAGS -o main$EXEEXT main.$OBJEXT liba.la],
+	   [], [ignore], [ignore])
+  LT_AT_EXEC_CHECK([./main])
+done
+
+AT_CLEANUP
-- 
1.7.9
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.