delorie.com/archives/browse.cgi   search  
Mail Archives: cygwin/2003/01/11/20:09:00

Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm
List-Subscribe: <mailto:cygwin-subscribe AT cygwin DOT com>
List-Archive: <http://sources.redhat.com/ml/cygwin/>
List-Post: <mailto:cygwin AT cygwin DOT com>
List-Help: <mailto:cygwin-help AT cygwin DOT com>, <http://sources.redhat.com/ml/#faqs>
Sender: cygwin-owner AT cygwin DOT com
Mail-Followup-To: cygwin AT cygwin DOT com
Delivered-To: mailing list cygwin AT cygwin DOT com
Message-ID: <3E20BF9A.4080400@ece.gatech.edu>
Date: Sat, 11 Jan 2003 20:06:34 -0500
From: Charles Wilson <cwilson AT ece DOT gatech DOT edu>
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.0.1) Gecko/20020823 Netscape/7.0
X-Accept-Language: en-us, en
MIME-Version: 1.0
To: Alexandre Duret-Lutz <duret_g AT lrde DOT epita DOT fr>
CC: automake-patches AT gnu DOT org, libtool-patches AT gnu DOT org, cygwin AT cygwin DOT com,
mingw-users AT lists DOT sourceforge DOT net
Subject: Re: Solving the "relink exe's" libtool problem [take 2]
References: <3E19C657 DOT 1040904 AT ece DOT gatech DOT edu> <2003-01-09-17-11-09+16471+duret_g AT lrde DOT epita DOT fr> <3E1DE146 DOT 8030901 AT ece DOT gatech DOT edu> <2003-01-09-23-01-51+2104+duret_g AT lrde DOT epita DOT fr>

--------------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 -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019