This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] PE direct linking to dlls, accept any filename.


Danny Smith wrote:
>
> Pedro Alves
> Tuesday, 19 December 2006 12:47 a.m.
>>
>>Danny Smith wrote:
>>
>>
>>>Could you add a test for symlinks (on cygwin), eg where
>>
>>
>>
>>I've added tests for symlinks.  Should I guard them for MinGW?  How?
>>The symlink functionality comes from the host not from the target.
>>Using msys or 'gcc -mno-cygwin' should work, no?
>>
>
>
> Mingw-hosted ld.exe (whether in  msys env  or built with -mno-cygwin,
> depends on MS msvcrt.dll,
> which has not a clue about cygwin symlinks. Cygwin-hosted ld.exe depends
> on cygwin1.dll so does recognize symlinks.
>
>

I understand that.  What I was missing, was the fact that you probably
are using cygwin to drive dejagnu, but building with
--host=i686-pc-mingw32.
Well, I tried doing the same and this is what I came up with.

First, I tried puting c:/MinGW first on the PATH, and then building with
configure --host=i686-pc-mingw32 --target=i686-pc-mingw32.  That has
the problem that absolute paths won't match between cygwin and MinGW, so
I came up with the scripts in the attached cygming_wrappers.tar.gz.
They are wrappers around gcc, g++, gas and ld, which will do the path
translation using cygpath.  Works pretty well, but to run the testsuite,
we would need the mingw.exp --host_board file attached.  It was only after
doing this, that I realized that MinGW understands the /mingw path, so
if I do a /mingw mount on cygwin, the paths will match in both environments.
Next, I put the binutils sources under /mingw/src, and I don't need the
scripts anymore. :) Talk about overengineering. :)
Well, the scripts are still useful, me thinks, because they allow me to
build MinGW stuff even when the sources are not under /mingw.  It is
just for the testsuite that they become a nuisance.  So, I attached
them anyway since someone may find them useful.  (Of course, they are
a proof of concept, so don't expect them to be complete, or even fully correct.
But, they did build binutils.  )

Now back to the /mingw mount mode.

I now see the problem you where seing.  Cygwin's ln -s puts a symlink
under tmpdir/ld, but the mingw/msvcrt ld doesn't understand it.  To
me this sounds clearly as a "if I do this, then it breaks. Then don't"
do it!" case.  I solved it in two ways.  One without any changes to
binutils whatsoever, and another one with a testsuite patch.

-  The first solution was to devise an "ln" wrapper script, that filters
out "-s | --symlink" and converts a symlink request into a hardlink,
which resolves to a copy on Windows.  This makes cygwin's ln look like
msys ln.  This works pretty well, and doesn't need any change in
binutils, but it is awkward to have to remember to put that script on
the PATH.

- The second solution is to change a bit the testsuite to detect
when we are building a mingw target under cygwin.  That is implemented
in the diff attached.  I only implemented it in ld, but if this is
wanted I can provide patches for the rest of the testsuites.

What do you guys think?  Both versions of the "ln -s" fix look ugly, but
I would rather go the with the testsuite fix.

Cheers,
Pedro Alves

Attachment: cygming_wrappers.tar.gz
Description: application/gzip

#!/bin/bash
#
# A wrapper for calling stripping the -s and --symlink options from ln invocations.
# Author: Pedro Alves <pedro_alves@portugalmail.pt>
# Version: 0.01
#

ME="`basename $0`"
EXEC_CMD="/usr/bin/ln"

#exec -a "$ME" "$EXEC_CMD" "$@"
echo "------------------------------------------------------------------------------"

TARGET=""
LINK_NAME=""

ARGS=""
while [ -n "$1" ]; do
   arg="$1"
   shift
   case "$arg" in
      -s | --sy*)
         continue
         ;;
      --*s*)
         ;;
      -*s*)
         arg=`echo ${arg} | sed s/s//g`
         ;;
      -*)
         ;;
      *)
         if [ "x$TARGET" = "x" ]; then
           TARGET=$arg
         elif [ "x$LINK_NAME" = "x" ]; then
           LINK_NAME=$arg
         fi
         continue
         ;;
   esac
   ARGS="$ARGS '$arg'"
done

if [ "x$TARGET" != "x" ] && [ "x$LINK_NAME" != "x" ]; then
  DIR=`dirname $LINK_NAME`
  TARGET=$DIR/$TARGET
fi

eval "set -- $ARGS $TARGET $LINK_NAME"

echo "$EXEC_CMD" "$@"
exec -a "$ME" "$EXEC_CMD" "$@"
Index: ld/testsuite/config/default.exp
===================================================================
RCS file: /cvs/src/src/ld/testsuite/config/default.exp,v
retrieving revision 1.11
diff -u -p -r1.11 default.exp
--- ld/testsuite/config/default.exp	27 May 2005 17:27:03 -0000	1.11
+++ ld/testsuite/config/default.exp	21 Dec 2006 12:43:33 -0000
@@ -51,12 +51,37 @@ if {![file isdirectory tmpdir]} then {
     catch "exec mkdir tmpdir" status
 }
 
+#
+# ld_symlink
+#	ln -s wrapper
+#
+proc ld_symlink { target link_name up_result } {
+    upvar 1 $up_result result
+    set uname "unknown"
+    catch "exec uname -o " uname
+  
+    if { [string match $uname "Cygwin"] && [istarget *-pc-mingw*] } {
+        # If a relative path was passed, we must adjust
+        # target, since in symlinks they are relative to link_name,
+        # while in cp, they are relative to $pwd    
+        if { [string first "/" $target] != 0 } {
+            set dirname [file dirname $link_name]
+            if { [string compare $dirname ""] != 0 } {      
+                set target "$dirname/$target"
+            }
+    }
+    catch "exec cp $target $link_name" result
+  } else {
+    catch "exec ln -s $target $link_name " result
+  }
+}
+
 # Make a symlink from tmpdir/as to the assembler in the build tree, so
 # that we can use a -B option to gcc to force it to use the newly
 # built assembler.
 if {![file isdirectory tmpdir/gas]} then {
     catch "exec mkdir tmpdir/gas" status
-    catch "exec ln -s ../../../gas/as-new tmpdir/gas/as" status
+    ld_symlink "../../../gas/as-new" "tmpdir/gas/as" status
 }
 set gcc_gas_flag "-B[pwd]/tmpdir/gas/"
 
@@ -65,7 +90,9 @@ set gcc_gas_flag "-B[pwd]/tmpdir/gas/"
 # built linker. 
 if {![file isdirectory tmpdir/ld]} then {
     catch "exec mkdir tmpdir/ld" status
-    catch "exec ln -s ../../ld-new tmpdir/ld/ld" status
+    verbose "calling ld_symlink "../../ld-new" "tmpdir/ld/ld""
+    ld_symlink "../../ld-new" "tmpdir/ld/ld" status
+    verbose "status=$status"
 }
 set gcc_ld_flag "-B[pwd]/tmpdir/ld/"
 
@@ -209,7 +236,7 @@ proc ld_nm { nm nmflags object } {
 
 #
 # ld_exec
-#	execute ithe target
+#	execute the target
 #
 proc ld_exec { target output } {
 	default_ld_exec $target $output
Index: ld/testsuite/ld-pe/direct.exp
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-pe/direct.exp,v
retrieving revision 1.1
diff -u -p -r1.1 direct.exp
--- ld/testsuite/ld-pe/direct.exp	19 Dec 2006 01:51:02 -0000	1.1
+++ ld/testsuite/ld-pe/direct.exp	21 Dec 2006 11:58:19 -0000
@@ -97,7 +97,8 @@ proc test_direct_link_dll {} {
 
 	    # Check dll direct linking through symlink to .dll.
 	    # Create symbolic link.
-	    catch "exec ln -fs direct_dll.dll $tmpdir/libdirect_dll.dll.a" ln_catch
+	    catch "exec rm -f $tmpdir/libdirect_dll.dll.a" ln_catch
+	    ld_symlink direct_dll.dll $tmpdir/libdirect_dll.dll.a ln_catch
 	    set msg "linking client (symlink -> .dll)"
 	    if [ld_simple_link $CC $tmpdir/direct_client_symlink_dll.exe "$tmpdir/direct_client.o $tmpdir/libdirect_dll.dll.a" ] {
 	        pass $msg
@@ -107,7 +108,8 @@ proc test_direct_link_dll {} {
 		
 	    # Check dll direct linking through symlink to .sl.
 	    # Create symbolic link.
-	    catch "exec ln -fs direct_dll.sl $tmpdir/libdirect_sl.dll.a" ln_catch
+	    catch "exec rm -f $tmpdir/libdirect_sl.dll.a" ln_catch
+	    ld_symlink direct_dll.sl $tmpdir/libdirect_sl.dll.a ln_catch
 	    set msg "linking client (symlink -> .sl)"
 	    if [ld_simple_link $CC $tmpdir/direct_client_symlink_sl.exe "$tmpdir/direct_client.o $tmpdir/libdirect_sl.dll.a" ] {
 		pass $msg
# The canonical unix board description.
load_generic_config "unix";

process_multilib_options "";

set_board_info compiler  "[find_gcc]";

set_board_info bmk,use_alarm 1;

set_board_info gdb,noinferiorio 1;

set_board_info use_cygpath 1;

#Need a way to auto-detect which testsuite is running
#so the set AS* below always work...

#These are needed for the gas testsuite
set AS_NEW [findfile $base_dir/../as-new "../as-new" [transform as]]
set AS "as-new $AS_NEW";

#These are needed for the ld testsuite
#set as_new [findfile $base_dir/../gas/as-new $base_dir/../gas/as-new [transform as]]
set as_new $base_dir/../gas/as-new
set as "as-new $as_new";
set AS "as-new $as_new";
set ld_new [findfile $base_dir/ld-new $base_dir/ld-new [transform ld]]
set ld "ld-new $ld_new";
set LD "ld-new $ld_new";

set_board_info ldflags "-Wl,--enable-auto-import"

send_user "configuring for mingw testing\n";

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]