[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[patch] win32: eliminate wrapper script in main build dir
From: |
Charles Wilson |
Subject: |
[patch] win32: eliminate wrapper script in main build dir |
Date: |
Sun, 10 Jun 2007 14:23:58 -0400 |
User-agent: |
Thunderbird 1.5.0.12 (Windows/20070509) |
This patch is an updated version of the one posted here:
http://lists.gnu.org/archive/html/libtool-patches/2007-04/msg00052.html
It is updated to reflect ongoing changes in HEAD, and avoids the mingw
regressions mentioned in that email.
Theory:
================================================================
On cygwin/mingw, a wrapper executable is used which should invoke a
wrapper script that is the typical libtool wrapper script used on other
platforms. However, it should be hidden inside $objdir, and given a
name distinct from its target. I chose:
.libs/foo_ltshwrapper
The exectuable wrapper generates this file, on the fly, every time it is
invoked. Therefore, this wrapper script *does not exist* until the
target executable is invoked. This behavior is already incorporated in
libtool-HEAD.
In general, libtool ALSO uses the wrapper script to "save" information
about the target, and often sources it. On mingw/cygwin, this patch
insures that a suitable wrapper script is generated at the same time the
wrapper executable is created -- in fact, with this patch libtool now
uses the wrapper executable to generate it. However, I choose a
*different* name than the one above:
.libs/foo_ltshwrapperTMP
Of course, other platforms continue to create a wrapper script as ./foo
and do not use the executable wrapper at all.
Thus, with this patch, the '.' directory will contain only wrapper
executables, and no wrapper scripts -- eliminating "foo.exe" vs "foo"
confusion. In $objdir, there will exist
.libs/foo.exe
.libs/foo_ltshwrapperTMP
.libs/foo_ltshwrapper [ recreated on-demand ]
(okay, maybe the names are backwards, but that's a two line cosmetic patch)
Now, it is possible that we could use the *same* .libs/foo_ltshwrapper
file for both "execute" and "func_source" purposes. However:
(a) I never want the executable wrapper to fail because the
wrapper script is missing
(b) I don't want the timestamp of the func_source()'ed wrapper
script to depend on whether/when the target was executed
(c) It is possible that, in the future, we will need to store
different state in one of these two: for instance, the
wrapper executable may eventually take another cmdline arg
like "--lt-relink-cmd '.....'". By using separate files,
one "invisible" (created on the fly by the executable wrapper
as a transparent part of its execv()-the-target proess), and
one "visible" that is timestamped at the same time as the
executable wrapper, we retain enough flexibility for the
future.
I'd like to be able to delete the "invisible" wrapper script after use,
but that's hard to arrange since we're using execv(): there is no
execv(target)-and-tell-target-to-delete-itself-afterwards.
On mingw, we (now) use _spawnv() and wait for the child, so presumably
on that platform we could delete the on-the-fly wrapper script after
use. But (1) I don't want mingw and cygwin to behave differently (one
cleans up the temporary wrapper, the other doesn't), and (2) I'm not
ready to change the wrapper's behavior in general to be wait-for-child.
I did it on mingw out of necessity (see below). In any case, the
execv-vs-spawnv and delete-after-use behavior can be addressed later.
Comments?
Portability issue?
================================================================
Implementation of func_ltwrapper_executable_p() greps $1 for the
expanded form of $magic. This works because the wrapper executable
contains the wrapper script contents verbatim, and the wrapper script
tests $libtool_install_magic against the expanded $magic.
We're already grepping binary files, without this patch.
func_ltwrapper_p() can (and often is) called with a binary as $1.
However, it delegates to func_lalib_p(), which does:
$SED -e 4q "$1" 2>/dev/null \
| $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1
Mingw-specific
================================================================
The original version of this patch -- and my initial forward port of it
to current HEAD -- induced new testsuite regressions on mingw:
< PASS: tests/demo-relink.test
> FAIL: tests/demo-relink.test
< PASS: tests/depdemo-relink.test
> FAIL: tests/depdemo-relink.test
26: DESTDIR with in-package deplibs FAILED (destdir.at:131)
29: C subdir-objects FAILED (am-subdir.at:81)
50: config.status FAILED (early-libtool.at:115)
51: config.lt FAILED (early-libtool.at:220)
These turned out to be side effects of the wrapper script no longer
being present in the main build dir. Up to this point, the msys shell
was always using the wrapper script and not the wrapper executable.
However, with the wrapper script missing, msys was now forced to use the
wrapper executable. Because on mingw, execv() doesn't actually replace
the current process, all 'expect fail' tests were getting an exit code
of 0 -- from the wrapper. Hence, on mingw we now use _spawnv(), and
manually pass the child's return value back to the caller.
Also, $OBJDUMP fails badly when called on a non-existant file, so some
$EXEEXT fixups in destdir.at were needed. These two changes, included
in the attached patch, eliminated the new regressions on mingw and
caused no issues on linux or cygwin.
So, using the final version of the patch (as attached):
TEST RESULTS:
=================================================
___________________________________________________________
cygwin
======================
All 115 tests passed
(9 tests were not run)
======================
14: Java convenience archives FAILED (convenience.at:273)
16: Link order of deplibs. FAILED (link-order2.at:129)
32: lt_dlopenadvise library loading FAILED (lt_dladvise.at:316)
54: Run tests with low max_cmd_len FAILED (cmdline_wrap.at:43)
This is the expected output, for now.
___________________________________________________________
mingw (assuming you 'export INSTALL=/usr/bin/install.exe')
====================================
All 115 tests passed
(9 tests were not run)
====================================
14: Java convenience archives FAILED (convenience.at:273)
16: Link order of deplibs. FAILED (link-order2.at:129)
32: lt_dlopenadvise library loading FAILED (lt_dladvise.at:314)
54: Run tests with low max_cmd_len FAILED (cmdline_wrap.at:43)
These are the same as cygwin.
None of these errors represent regressions on this platform.
___________________________________________________________
Linux
====================
All 106 tests passed
====================
52 tests behaved as expected.
2 tests were skipped.
CHANGELOG
=================================================
2007-04-22 Charles Wilson <address@hidden>
* libltdl/config/ltmain.m4sh (func_ltwrapper_script_p):
new function detects if $1 is a libtool sh wrapper
(func_ltwrapper_executable_p): new function detects
if $1 is a libtool executable wrapper
(func_ltwrapper_p): modified to detect is $1 is ANY
sort of libtool wrapper
(func_ltwrapper_temp_scriptname): new function generates
appropriate pathname for temporary libtool wrapper script
if libtool executable wrappers are in use. This temporary
script is suitable for use with func_source().
(func_mode_execute): handle $file that is a libtool wrapper
script and $file that is a libtool wrapper executable
differently.
(func_mode_install) [cygwin|mingw]: if $file is a libtool
wrapper executable, use func_ltwrapper_temp_scriptname()
to determine wrapper script name. After determining name
of wrapper script, use func_ltwrapper_script_p() instead
of func_ltwrapper_p().
(func_mode_link) [cygwin|mingw]: don't call dirname and
basename directly; use func_dirname() and func_basename()
when computing cwrapper names. Use cwrapper to generate
wrapper script, and use pathname returned by
func_ltwrapper_temp_scriptname() instead of $output.
(func_mode_link) [NOT cygwin|mingw]: move wrapper script
generation for non-win32 inside case statement, as default
case.
(func_mode_uninstall) [$name's extension != .lo|.la]:
'clean' mode must handle $file differently if it is a libtool
wrapper script, or if it is a libtool wrapper executable.
(func_emit_libtool_cwrapperexe_source) [main, mingw]:
use _spawnv and return child's exit code manually rather
than rely on (broken) execv.
* tests/destdir.at: $EXEEXT fixups.
Index: libltdl/config/ltmain.m4sh
===================================================================
RCS file: /cvsroot/libtool/libtool/libltdl/config/ltmain.m4sh,v
retrieving revision 1.79
diff -u -r1.79 ltmain.m4sh
--- libltdl/config/ltmain.m4sh 9 Jun 2007 17:46:40 -0000 1.79
+++ libltdl/config/ltmain.m4sh 10 Jun 2007 07:22:05 -0000
@@ -661,13 +661,61 @@
test "$lalib_p" = yes
}
+# func_ltwrapper_script_p file
+# True iff FILE is a libtool wrapper script
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_ltwrapper_script_p ()
+{
+ func_lalib_p "$1"
+}
+
+# func_ltwrapper_executable_p file
+# True iff FILE is a libtool wrapper executable
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_ltwrapper_executable_p ()
+{
+ func_ltwrapper_executable_p_result=no
+ if ! func_ltwrapper_script_p "$1" ; then
+ case "$1" in
+ *.exe ) if grep "$magic" "$1" >/dev/null ; then
+ func_ltwrapper_executable_p_result=yes
+ fi ;;
+ * ) if grep "$magic" "${1}.exe" >/dev/null ; then
+ func_ltwrapper_executable_p_result=yes
+ fi ;;
+ esac
+ fi
+ test "$func_ltwrapper_executable_p_result" = "yes"
+}
+
+# func_ltwrapper_temp_scriptname file
+# Assumes file is an ltwrapper_executable
+# uses $file to determine the appropriate filename for a
+# temporary ltwrapper_script.
+func_ltwrapper_temp_scriptname ()
+{
+ func_ltwrapper_temp_scriptname_result=""
+ if func_ltwrapper_executable_p "$1"; then
+ func_dirname "$1"
+ func_basename "$1"
+ func_stripname '' '.exe' "$func_basename_result"
+ if test -z "$func_dirname_result"; then
+
func_ltwrapper_temp_scriptname_result="./$objdir/${func_stripname_result}_ltshwrapperTMP"
+ else
+
func_ltwrapper_temp_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapperTMP"
+ fi
+ fi
+}
+
# func_ltwrapper_p file
-# True iff FILE is a libtool wrapper script.
+# True iff FILE is a libtool wrapper script or wrapper executable
# This function is only a basic sanity check; it will hardly flush out
# determined imposters.
func_ltwrapper_p ()
{
- func_lalib_p "$1"
+ func_ltwrapper_script_p "$1" || func_ltwrapper_execuable_p "$1"
}
@@ -1649,11 +1697,17 @@
-*) ;;
*)
# Do a test to see if this is really a libtool program.
- if func_ltwrapper_p "$file"; then
- func_source "$file"
-
+ if func_ltwrapper_script_p "$file"; then
+ func_source "$file"
# Transform arg to wrapped name.
file="$progdir/$program"
+ else
+ if func_ltwrapper_executable_p "$file"; then
+ func_ltwrapper_temp_scriptname "$file"
+ func_source "$func_ltwrapper_temp_scriptname_result"
+ # Transform arg to wrapped name.
+ file="$progdir/$program"
+ fi
fi
;;
esac
@@ -2085,14 +2139,19 @@
# Do a test to see if this is really a libtool program.
case $host in
*cygwin*|*mingw*)
- func_stripname '' '.exe' "$file"
- wrapper=$func_stripname_result
+ if func_ltwrapper_executable_p "$file"; then
+ func_ltwrapper_temp_scriptname "$file"
+ wrapper="$func_ltwrapper_temp_scriptname_result"
+ else
+ func_stripname '' '.exe' "$file"
+ wrapper="$func_stripname_result"
+ fi
;;
*)
wrapper=$file
;;
esac
- if func_ltwrapper_p "$wrapper"; then
+ if func_ltwrapper_script_p "$wrapper"; then
notinst_deplibs=
relink_command=
@@ -2561,6 +2620,7 @@
char *tmp_pathspec;
char *actual_cwrapper_path;
char *shwrapper_name;
+ intptr_t rval = 127;
FILE *shwrapper;
const char *dumpscript_opt = "--lt-dump-script";
@@ -2688,19 +2748,28 @@
case $host_os in
mingw*)
cat <<EOF
- execv ("$lt_newargv0", (const char * const *) newargz);
+ /* execv doesn't actually work on mingw as expected on unix */
+ rval = _spawnv (_P_WAIT, "$lt_newargv0", (const char * const *) newargz);
+ if (rval == -1)
+ {
+ /* failed to start process */
+ LTWRAPPER_DEBUGPRINTF (("(main) failed to launch target
\"$lt_newargv0\": errno = %d\n", errno));
+ return 127;
+ }
+ return rval;
+}
EOF
;;
*)
cat <<EOF
execv ("$lt_newargv0", newargz);
+ return rval; /* =127, but avoids unused variable warning */
+}
EOF
;;
esac
cat <<"EOF"
- return 127;
-}
void *
xmalloc (size_t num)
@@ -6708,8 +6777,13 @@
esac
case $host in
*cygwin* | *mingw* )
- output_name=`basename $output`
- output_path=`dirname $output`
+ func_basename "$output"
+ output_name="$func_basename_result"
+ func_dirname "$output"
+ output_path="$func_dirname_result"
+ if test -z "$output_path"; then
+ output_path=.
+ fi
cwrappersource="$output_path/$objdir/lt-$output_name.c"
cwrapper="$output_path/$output_name.exe"
$RM $cwrappersource $cwrapper
@@ -6717,19 +6791,30 @@
func_emit_libtool_cwrapperexe_source > $cwrappersource
- # we should really use a build-platform specific compiler
- # here, but OTOH, the wrappers (shell script and this C one)
- # are only useful if you want to execute the "real" binary.
- # Since the "real" binary is built for $host, then this
- # wrapper might as well be built for $host, too.
- $opt_dry_run || $LTCC $LTCFLAGS -s -o $cwrapper $cwrappersource
+ # we should really use a build-platform specific compiler
+ # here, but OTOH, the wrappers (shell script and this C one)
+ # are only useful if you want to execute the "real" binary.
+ # Since the "real" binary is built for $host, then this
+ # wrapper might as well be built for $host, too.
+ $opt_dry_run || $LTCC $LTCFLAGS -s -o $cwrapper $cwrappersource
+
+ # Now, create the wrapper script for func_source use:
+ func_ltwrapper_temp_scriptname $cwrapper
+ $RM $func_ltwrapper_temp_scriptname_result
+ trap "$RM $func_ltwrapper_temp_scriptname_result; exit
$EXIT_FAILURE" 1 2 15
+ $opt_dry_run || {
+ $cwrapper --lt-dump-script >
$func_ltwrapper_temp_scriptname_result
+ }
+ chmod +x $func_ltwrapper_temp_scriptname_result
+ ;;
+ * )
+ $RM $output
+ trap "$RM $output; exit $EXIT_FAILURE" 1 2 15
+
+ func_emit_libtool_wrapper_script no > $output
+ chmod +x $output
;;
esac
- $RM $output
- trap "$RM $output; exit $EXIT_FAILURE" 1 2 15
-
- func_emit_libtool_wrapper_script no > $output
- chmod +x $output
}
exit $EXIT_SUCCESS
;;
@@ -7179,8 +7264,15 @@
esac
# Do a test to see if this is a libtool program.
if func_ltwrapper_p "$file"; then
- relink_command=
- func_source $dir/$noexename
+ if func_ltwrapper_executable_p "$file"; then
+ func_ltwrapper_temp_scriptname "$file"
+ relink_command=
+ func_source $func_ltwrapper_temp_scriptname_result
+ rmfiles="$rmfiles $func_ltwrapper_temp_scriptname_result"
+ else
+ relink_command=
+ func_source $dir/$noexename
+ fi
# note $name still contains .exe if it was in $file originally
# as does the version of $file that was added into $rmfiles
Index: tests/destdir.at
===================================================================
RCS file: /cvsroot/libtool/libtool/tests/destdir.at,v
retrieving revision 1.5
diff -u -r1.5 destdir.at
--- tests/destdir.at 25 Mar 2007 12:12:43 -0000 1.5
+++ tests/destdir.at 10 Jun 2007 07:22:05 -0000
@@ -127,8 +127,8 @@
LT_AT_EXEC_CHECK([$bindir/m])
# TODO: make this more portable:
-if test "$OBJDUMP" != false && ($OBJDUMP -p $bindir/m) >/dev/null 2>&1; then
- AT_CHECK([$OBJDUMP -p $bindir/m | $EGREP -i "R(UN)?PATH.*$DESTDIR"], [1])
+if test "$OBJDUMP" != false && ($OBJDUMP -p $bindir/m$EXEEXT) >/dev/null 2>&1;
then
+ AT_CHECK([$OBJDUMP -p $bindir/m$EXEEXT | $EGREP -i "R(UN)?PATH.*$DESTDIR"],
[1])
. $libdir/liba.la
set x $library_names
lname=$2
- [patch] win32: eliminate wrapper script in main build dir,
Charles Wilson <=
- Re: [patch] win32: eliminate wrapper script in main build dir, Noah Misch, 2007/06/14
- Re: [patch] win32: eliminate wrapper script in main build dir, Ralf Wildenhues, 2007/06/16
- Re: [patch] win32: eliminate wrapper script in main build dir, Ralf Wildenhues, 2007/06/16
- Re: [patch] win32: eliminate wrapper script in main build dir, Charles Wilson, 2007/06/16
- Re: [patch] win32: eliminate wrapper script in main build dir, Ralf Wildenhues, 2007/06/17
- Re: [patch] win32: eliminate wrapper script in main build dir, Charles Wilson, 2007/06/17
- Re: [patch] win32: eliminate wrapper script in main build dir, Ralf Wildenhues, 2007/06/17
- Re: [patch] win32: eliminate wrapper script in main build dir, Charles Wilson, 2007/06/17
- Re: [patch] win32: eliminate wrapper script in main build dir, Charles Wilson, 2007/06/19