Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm List-Subscribe: List-Archive: List-Post: List-Help: , 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 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 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> Content-Type: multipart/mixed; boundary="------------050909090604070107050004" --------------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: /foo (shell wrapper) /foo.exe (binary wrapper) /lt-foo.c /.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 * 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 <> $cwrappersource<<"EOF" +#include +#include +#include +#include +#include +#include + +#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--