Mail Archives: cygwin/2003/01/11/20:09:00
--------------050909090604070107050004
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit
Alexandre Duret-Lutz wrote:
> Chuck> Said "stub" executable would have to do ALL of the
> Chuck> things the script does, and then pass that environment
> Chuck> to its exec'ed target in .libs/ --
>
> Maybe it could just exec() something like `/bin/sh .libs/foo.sh',
> where `.libs/foo.sh' is the script wrapper.
Good idea. Try this version...
It no longer requires any coordination with automake; it's all
implemented in ltmain.sh and doesn't mess with EXEEXT or LT_EXEEXT.
Now, this isn't perfect -- it solves the problem, has no regressions on
cygwin, and is probably okay for inclusion in libtool CVS. But there
are stylistic warts that could be sanded off, if someone else were to
take the effort (hint, hint)
The following behavior is only "active" when $host is cygwin or mingw:
I left the shell wrapper where it was, in the build directory. When
creating the shell wrapper, libtool will also create lt-${prog}.c and
compile it using
$run $LTCC -s -o ${prog}.exe lt-${prog}.c
So, you end up with:
<builddir>/foo (shell wrapper)
<builddir>/foo.exe (binary wrapper)
<builddir>/lt-foo.c
<builddir>/.libs/foo.exe (the real executable)
Since builddir contains foo.exe, make is happy. ./foo.exe execs
"/bin/sh foo", which sets up the environment and calls .libs/foo.exe.
Eventually, the functionality of the shell wrapper could be moved into
the source code for the binary wrapper, and we could drop the shell
wrapper completely for cygwin/mingw $host.
So the fact that the shell wrapper is still there is a wart (but
removing the shell wrapper creates its own difficulties -- see next point).
There are two places in ltmain.sh where the shell wrapper is directly
sourced. This doesn't work very well, because when both "foo" and
"foo.exe" exist, ". ./foo" ends up sourcing "foo.exe" -- which is bad.
[Note, if the shell wrapper is eliminated, then somehow libtool needs to
be able to get the info embedded into the binary wrapper. Maybe the
binary wrapper needs a "--shell" option, that emits what is effectively
the current shell script? But then, that's just another wart (`binwrap
--shell > shellwrap`; . shellwrap ; rm shellwrap), unless there is a way
to "source" rather than execute the contents of a variable.]
But, if both the binary wrapper and the shell wrapper exist, there are a
few ways to solve the conflict that occurs when libtool tries to source
the shell wrapper (and sources the binary wrapper instead):
(1) prior to directly sourcing the shell wrapper into libtool's
memory space, make a temporary copy with a name that doesn't conflict
with "foo.exe" in the same way that "foo" does. E.g.
cp foo lt-foo.sh
. ./lt-foo.sh
rm -f lt-foo.sh
Yes, it's a race condition, but it should be temporary pending further
work...
(2) on the cygwin/mingw platforms, change the name of the shell
wrapper itself. So don't create "foo" at all; instead, create lt-foo.sh
(or .libs/foo.sh). But this requires catching ALL of the places were
$output or $outputname are set, and fixing them with case $host ;
*cgywin* | *mingw* ) ... ;; esac blocks. Blech.
I did #1, as it appeared to require fewer modifications. ($output and
$outputname are set in SO many different places...) Plus, I anticipate
that, at least on cygwin/mingw, we might eventually completely do away
with the shell wrapper by incorporating its functionality within the
binary wrapper(given the caveats re: --shell above)...an added incentive
to avoid disrupting the rest of ltmain.sh beyond the absolute minimum.
Also, there may be some complaints about using $LTCC to build the binary
wrapper, especially in the context of a cross compiler. Here's a block
of comments from the patch:
# 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.
$run $LTCC -s -o $cwrapper $cwrappersource
--------------------------------------
cgywin: if you've already installed my test versions of automake and
libtool (automake-devel-1.7.2-2 and libtool-devel-20030103-2), you must
revert to the "REAL" cygwin automake-devel-1.7.2-1. Then, update to
libtool-devel-20030103-3 which is now available by pointing setup.exe at
http://www.neuro.gatech.edu/users/cwilson/cygutils/testing/
mingw: test reports?
automake: please ignore the previously posted patch
libtool: Hopefully this gives a starting point for further refinement.
But IMO it is okay (e.g. functional) for inclusion into CVS as-is,
provided that it causes no problems on non-windows, and fixes the
relink-exe problem on mingw. It DOES fix the relink-exe problem on cygwin.
---------------------------------------
--Chuck
--------------050909090604070107050004
Content-Type: text/plain;
name="libtool-relinkexe2.changelog"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="libtool-relinkexe2.changelog"
2003-01-11 Charles Wilson <cwilson AT ece DOT gatech DOT edu>
* ltmain.in: add code for a binary wrapper
to use with uninstalled executables on cygwin/mingw.
To work around a feature of the cygwin/MSYS shell,
temporarily create a copy of the shell wrapper under
a different name before sourcing it (otherwise,
the binary wrapper gets sourced, instead...)
--------------050909090604070107050004
Content-Type: text/plain;
name="libtool-relinkexe2.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="libtool-relinkexe2.patch"
Index: ltmain.in
===================================================================
RCS file: /cvsroot/libtool/libtool/ltmain.in,v
retrieving revision 1.318
diff -u -u -r1.318 ltmain.in
--- ltmain.in 1 Jan 2003 01:57:47 -0000 1.318
+++ ltmain.in 11 Jan 2003 20:00:37 -0000
@@ -4284,6 +4284,201 @@
outputname=`echo $outputname|${SED} 's,.exe$,,'` ;;
*) exeext= ;;
esac
+ case $host in
+ *cygwin* | *mingw* )
+ cwrappersource=`echo lt-$output|${SED} 's,$,.c,'`
+ cwrapper=`echo $output|${SED} 's,$,.exe,'`
+ $rm $cwrappersource $cwrapper
+ trap "$fm $cwrappersource $cwrapper; exit 1" 1 2 15
+
+ cat > $cwrappersource <<EOF
+
+/* $cwrappersource - temporary wrapper executable for $objdir/$outputname
+ Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+
+ The $output program cannot be directly executed until all the libtool
+ libraries that it depends on are installed.
+
+ This wrapper executable should never be moved out of the build directory.
+ If it is, it will not operate correctly.
+
+ Currently, it simply execs the wrapper *script* "/bin/sh $output",
+ but could eventually absorb all of the scripts functionality and
+ exec $objdir/$outputname directly.
+*/
+EOF
+ cat >> $cwrappersource<<"EOF"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <malloc.h>
+#include <stdarg.h>
+#include <assert.h>
+
+#if defined(PATH_MAX)
+# define LT_PATHMAX PATH_MAX
+#elif defined(MAXPATHLEN)
+# define LT_PATHMAX MAXPATHLEN
+#else
+# define LT_PATHMAX 1024
+#endif
+
+#ifndef DIR_SEPARATOR
+#define DIR_SEPARATOR '/'
+#endif
+
+#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \
+ defined (__OS2__)
+#define HAVE_DOS_BASED_FILE_SYSTEM
+#ifndef DIR_SEPARATOR_2
+#define DIR_SEPARATOR_2 '\\'
+#endif
+#endif
+
+#ifndef DIR_SEPARATOR_2
+# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
+#else /* DIR_SEPARATOR_2 */
+# define IS_DIR_SEPARATOR(ch) \
+ (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
+#endif /* DIR_SEPARATOR_2 */
+
+#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type)))
+#define XFREE(stale) do { \
+ if (stale) { free ((void *) stale); stale = 0; } \
+} while (0)
+
+const char *program_name = NULL;
+
+void * xmalloc (size_t num);
+char * xstrdup (const char *string);
+char * basename (const char *name);
+char * fnqualify(const char *path);
+char * strendzap(char *str, const char *pat);
+void lt_fatal (const char *message, ...);
+
+int
+main (int argc, char *argv[])
+{
+ char *full;
+
+ program_name = (char *) xstrdup ((char *) basename (argv[0]));
+ full = fnqualify(argv[0]);
+ /* we know the script has the same name, without the .exe */
+ /* so make sure full doesn't end in .exe */
+ strendzap(full,".exe");
+ execl("/bin/sh","/bin/sh",full,NULL);
+}
+
+void *
+xmalloc (size_t num)
+{
+ void * p = (void *) malloc (num);
+ if (!p)
+ lt_fatal ("Memory exhausted");
+
+ return p;
+}
+
+char *
+xstrdup (const char *string)
+{
+ return string ? strcpy ((char *) xmalloc (strlen (string) + 1), string) : NULL
+;
+}
+
+char *
+basename (const char *name)
+{
+ const char *base;
+
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+ /* Skip over the disk name in MSDOS pathnames. */
+ if (isalpha (name[0]) && name[1] == ':')
+ name += 2;
+#endif
+
+ for (base = name; *name; name++)
+ if (IS_DIR_SEPARATOR (*name))
+ base = name + 1;
+ return (char *) base;
+}
+
+char *
+fnqualify(const char *path)
+{
+ size_t size;
+ char *p;
+ char tmp[LT_PATHMAX + 1];
+
+ assert(path != NULL);
+
+ /* Is it qualified already? */
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+ if (isalpha (path[0]) && path[1] == ':')
+ return xstrdup (path);
+#endif
+ if (IS_DIR_SEPARATOR (path[0]))
+ return xstrdup (path);
+
+ /* prepend the current directory */
+ /* doesn't handle '~' */
+ if (getcwd (tmp, LT_PATHMAX) == NULL)
+ lt_fatal ("getcwd failed");
+ size = strlen(tmp) + 1 + strlen(path) + 1; /* +2 for '/' and '\0' */
+ p = XMALLOC(char, size);
+ sprintf(p, "%s%c%s", tmp, DIR_SEPARATOR, path);
+ return p;
+}
+
+char *
+strendzap(char *str, const char *pat)
+{
+ size_t len, patlen;
+
+ assert(str != NULL);
+ assert(pat != NULL);
+
+ len = strlen(str);
+ patlen = strlen(pat);
+
+ if (patlen <= len)
+ {
+ str += len - patlen;
+ if (strcmp(str, pat) == 0)
+ *str = '\0';
+ }
+ return str;
+}
+
+static void
+lt_error_core (int exit_status, const char * mode,
+ const char * message, va_list ap)
+{
+ fprintf (stderr, "%s: %s: ", program_name, mode);
+ vfprintf (stderr, message, ap);
+ fprintf (stderr, ".\n");
+
+ if (exit_status >= 0)
+ exit (exit_status);
+}
+
+void
+lt_fatal (const char *message, ...)
+{
+ va_list ap;
+ va_start (ap, message);
+ lt_error_core (EXIT_FAILURE, "FATAL", message, ap);
+ va_end (ap);
+}
+EOF
+ # 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.
+ $run $LTCC -s -o $cwrapper $cwrappersource
+ ;;
+ esac
$rm $output
trap "$rm $output; exit 1" 1 2 15
@@ -5066,8 +5261,12 @@
# If there is no directory component, then add one.
case $file in
- */* | *\\*) . $wrapper ;;
- *) . ./$wrapper ;;
+ */* | *\\*) cp ${wrapper} ${wrapper}-lt.sh
+ . ${wrapper}-lt.sh
+ $rm -f ${wrapper}-lt.sh ;;
+ *) cp ./${wrapper} ./${wrapper}-lt.sh
+ . ./${wrapper}-lt.sh
+ $rm -f ${wrapper}-lt.sh ;;
esac
# Check the variables that should have been set.
@@ -5097,8 +5296,12 @@
relink_command=
# If there is no directory component, then add one.
case $file in
- */* | *\\*) . $file ;;
- *) . ./$file ;;
+ */* | *\\*) cp ${wrapper} ${wrapper}-lt.sh
+ . ${wrapper}-lt.sh
+ $rm -f ${wrapper}-lt.sh ;;
+ *) cp ./${wrapper} ./${wrapper}-lt.sh
+ . ./${wrapper}-lt.sh
+ $rm -f ${wrapper}-lt.sh ;;
esac
outputname=
--------------050909090604070107050004
Content-Type: text/plain; charset=us-ascii
--
Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple
Bug reporting: http://cygwin.com/bugs.html
Documentation: http://cygwin.com/docs.html
FAQ: http://cygwin.com/faq/
--------------050909090604070107050004--
- Raw text -