]> git.ipfire.org Git - thirdparty/libtool.git/commitdiff
* ltmain.m4sh (func_emit_libtool_wrapper_script): add
authorCharles Wilson <libtool@cwilson.fastmail.fm>
Thu, 7 Jun 2007 08:47:11 +0000 (08:47 +0000)
committerCharles Wilson <libtool@cwilson.fastmail.fm>
Thu, 7 Jun 2007 08:47:11 +0000 (08:47 +0000)
code block to handle cases when wrapper script is in $objdir.
(func_emit_libtool_cwrapperexe_source): replace DEBUG() macro
with namespace-safe LTWRAPPER_DEBUGPRINTF(). Call
func_emit_libtool_wrapper_script() with appropriate filters to
embed script text in C char* static variable.
(f_e_l_c_s: main): add new option --lt-dump-script, parse argv[]
for it, and take appropriate action.  Call chase_symlinks()
on argv[0], in case this.exe was launched via one.  Use chased
value to determine full absolute pathname of wrapper script, in
$objdir. Unconditionally write script out to this pathname and
set permission bits.  Remove extraneous ';' from debugging loop.
(f_e_l_c_s: main) [mingw]: DOS-ize $SHELL before populating
newargv[0]; if $TARGETSHELL environment variable is set, use
it instead of $SHELL and do not DOS-ize.  Ensure newargv[1]
(wrapper script absolute path) uses only '/', not '\'.  Make
sure to call execv() with DOS-ized $SHELL (or un-DOS-ized
$TARGETSHELL, if set)
(f_e_l_c_s: make_executable): new function
(f_e_l_c_s: chase_symlinks): new function (no-op if !S_ISLNK)

ChangeLog
libltdl/config/ltmain.m4sh

index 43fbc6ce11e835911a51bb75b655363e51762ce4..d117be735b80f762781cb9091d83e4cc37faeb6d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,26 @@
+2007-04-27  Charles Wilson  <libtool@cwilson.fastmail.fm>
+
+       * ltmain.m4sh (func_emit_libtool_wrapper_script): add
+       code block to handle cases when wrapper script is in $objdir.
+       (func_emit_libtool_cwrapperexe_source): replace DEBUG() macro
+       with namespace-safe LTWRAPPER_DEBUGPRINTF(). Call
+       func_emit_libtool_wrapper_script() with appropriate filters to
+       embed script text in C char* static variable.
+       (f_e_l_c_s: main): add new option --lt-dump-script, parse argv[]
+       for it, and take appropriate action.  Call chase_symlinks()
+       on argv[0], in case this.exe was launched via one.  Use chased
+       value to determine full absolute pathname of wrapper script, in
+       $objdir. Unconditionally write script out to this pathname and
+       set permission bits.  Remove extraneous ';' from debugging loop.
+       (f_e_l_c_s: main) [mingw]: DOS-ize $SHELL before populating     
+       newargv[0]; if $TARGETSHELL environment variable is set, use 
+       it instead of $SHELL and do not DOS-ize.  Ensure newargv[1]
+       (wrapper script absolute path) uses only '/', not '\'.  Make
+       sure to call execv() with DOS-ized $SHELL (or un-DOS-ized
+       $TARGETSHELL, if set)
+       (f_e_l_c_s: make_executable): new function
+       (f_e_l_c_s: chase_symlinks): new function (no-op if !S_ISLNK)
+
 2007-06-03  Peter O'Gorman  <peter@pogma.com>
 
        * libltdl/m4/libtool.m4 (old_archive_cmds): Remove
index cd77364c65ed12dcf12d0f5a7ead22c94bb41c7a..b9d58fd903a5bb4394f25600e7890d37301564d5 100644 (file)
@@ -2301,6 +2301,20 @@ else
     file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\`
   done
 
+  # cygwin/mingw cwrapper will rewrite this line:
+  WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=no
+  if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then
+    # special case for '.'
+    if test \"\$thisdir\" = \".\"; then
+      thisdir=\`pwd\`
+    fi
+    # remove .libs from thisdir
+    case \"\$thisdir\" in
+    *[\\\\/]$objdir ) thisdir=\`\$ECHO \"X\$thisdir\" | \$Xsed -e 's%[\\\\/][^\\\\/]*$%%'\` ;;
+    $objdir )   thisdir=. ;;
+    esac
+  fi
+
   # Try to get the absolute directory name.
   absdir=\`cd \"\$thisdir\" && pwd\`
   test -n \"\$absdir\" && thisdir=\"\$absdir\"
@@ -2424,7 +2438,7 @@ func_emit_libtool_cwrapperexe_source ()
    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",
+   Currently, it simply execs the wrapper *script* "$SHELL $output",
    but could eventually absorb all of the scripts functionality and
    exec $objdir/$outputname directly.
 */
@@ -2438,6 +2452,7 @@ EOF
 #include <assert.h>
 #include <string.h>
 #include <ctype.h>
+#include <errno.h>
 #include <sys/stat.h>
 
 #if defined(PATH_MAX)
@@ -2482,12 +2497,11 @@ EOF
   if (stale) { free ((void *) stale); stale = 0; } \
 } while (0)
 
-/* -DDEBUG is fairly common in CFLAGS.  */
-#undef DEBUG
+#undef LTWRAPPER_DEBUGPRINTF
 #if defined DEBUGWRAPPER
-# define DEBUG(format, ...) fprintf(stderr, format, __VA_ARGS__)
+# define LTWRAPPER_DEBUGPRINTF(format, ...) fprintf(stderr, format, __VA_ARGS__)
 #else
-# define DEBUG(format, ...)
+# define LTWRAPPER_DEBUGPRINTF(format, ...)
 #endif
 
 const char *program_name = NULL;
@@ -2496,42 +2510,145 @@ void * xmalloc (size_t num);
 char * xstrdup (const char *string);
 const char * base_name (const char *name);
 char * find_executable(const char *wrapper);
+char * chase_symlinks(const char *pathspec);
+int    make_executable(const char *path);
 int    check_executable(const char *path);
 char * strendzap(char *str, const char *pat);
 void lt_fatal (const char *message, ...);
 
+static const char* script_text = 
+EOF
+
+           func_emit_libtool_wrapper_script |
+               $SED -e 's/\([\\"]\)/\\\1/g' \
+                    -e 's/\(WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\)=.*/\1=yes/' \
+                    -e 's/^/"/' -e 's/$/\\n"/' 
+           echo ";"
+
+           cat <<EOF
 int
 main (int argc, char *argv[])
 {
   char **newargz;
+  char *tmp_pathspec;
+  char *actual_cwrapper_path;
+  char *shwrapper_name;
+  FILE *shwrapper;
+
+  const char* dumpscript_opt = "--lt-dump-script";
   int i;
 
   program_name = (char *) xstrdup (base_name (argv[0]));
-  DEBUG("(main) argv[0]      : %s\n",argv[0]);
-  DEBUG("(main) program_name : %s\n",program_name);
+  LTWRAPPER_DEBUGPRINTF("(main) argv[0]      : %s\n",argv[0]);
+  LTWRAPPER_DEBUGPRINTF("(main) program_name : %s\n",program_name);
+
+  /* very simple arg parsing; don't want to rely on getopt */
+  for (i=1; i<argc; i++)
+  {
+    if (strcmp(argv[i], dumpscript_opt) == 0)
+    {
+      printf("%s", script_text);
+      return 0;
+    }
+  }
+
   newargz = XMALLOC(char *, argc+2);
 EOF
 
-           cat <<EOF
-  newargz[0] = (char *) xstrdup("$SHELL");
+           if test -n "$TARGETSHELL" ; then
+             # no path translation at all
+             lt_newargv0=$TARGETSHELL
+           else
+             case "$host" in
+               *mingw* )
+                 # awkward: cmd appends spaces to result
+                 lt_sed_strip_trailing_spaces="s/[ ]*\$//"
+                 lt_newargv0=`( cmd //c echo $SHELL | $SED -e "$lt_sed_strip_trailing_spaces" ) 2>/dev/null || echo $SHELL`
+                 case $lt_newargv0 in
+                   *.exe | *.EXE) ;;
+                   *) lt_newargv0=$lt_newargv0.exe ;;
+                 esac
+                 ;;
+               * ) lt_newargv0=$SHELL ;;
+             esac
+           fi 
+
+               cat <<EOF
+  newargz[0] = (char *) xstrdup("$lt_newargv0");
 EOF
 
            cat <<"EOF"
-  newargz[1] = find_executable(argv[0]);
-  if (newargz[1] == NULL)
+  tmp_pathspec = find_executable (argv[0]);
+  if (tmp_pathspec == NULL)
     lt_fatal("Couldn't find %s", argv[0]);
-  DEBUG("(main) found exe at : %s\n",newargz[1]);
-  /* we know the script has the same name, without the .exe */
-  /* so make sure newargz[1] doesn't end in .exe */
-  strendzap(newargz[1],".exe");
+  LTWRAPPER_DEBUGPRINTF("(main) found exe (before symlink chase) at : %s\n",tmp_pathspec);
+
+  actual_cwrapper_path = chase_symlinks (tmp_pathspec);
+  LTWRAPPER_DEBUGPRINTF("(main) found exe (after symlink chase) at : %s\n",actual_cwrapper_path);
+  XFREE(tmp_pathspec);
+
+  shwrapper_name = (char *) xstrdup (base_name (actual_cwrapper_path));
+  strendzap( actual_cwrapper_path, shwrapper_name );
+
+  /* shwrapper_name transforms */
+  strendzap(shwrapper_name,".exe");
+  tmp_pathspec = XMALLOC( char, strlen ( shwrapper_name ) +
+                                    strlen ( "_ltshwrapper" ) + 1 );
+  strcpy ( tmp_pathspec, shwrapper_name );
+  strcat ( tmp_pathspec, "_ltshwrapper" );
+  XFREE( shwrapper_name );
+  shwrapper_name = tmp_pathspec;
+  tmp_pathspec = 0;
+  LTWRAPPER_DEBUGPRINTF("(main) libtool shell wrapper name: %s\n",shwrapper_name);
+EOF
+
+           cat <<EOF
+  newargz[1] = XMALLOC( char, strlen ( actual_cwrapper_path ) +
+                              strlen ( "$objdir" ) + 1 +
+                              strlen ( shwrapper_name ) + 1 );
+  strcpy ( newargz[1], actual_cwrapper_path );
+  strcat ( newargz[1], "$objdir" );
+  strcat ( newargz[1], "/" );
+  strcat ( newargz[1], shwrapper_name );
+EOF
+
+
+           case $host_os in
+             mingw*)
+           cat <<"EOF"
+  {
+     char* p;
+     while( (p = strchr(newargz[1], '\\')) != NULL) {
+        *p = '/';
+     }
+  }
+EOF
+           ;;
+           esac
+
+           cat <<"EOF"
+  XFREE( shwrapper_name );
+  XFREE( actual_cwrapper_path );
+
+  /* note: do NOT use "wt" here! -- defer to underlying
+   * mount type on cygwin
+   */
+  if ( (shwrapper = fopen (newargz[1], "w")) == 0 )
+  {
+    lt_fatal("Could not open %s for writing", newargz[1]);
+  }
+  fprintf (shwrapper, "%s", script_text);
+  fclose (shwrapper);
+
+  make_executable( newargz[1] );
+  
   for (i = 1; i < argc; i++)
     newargz[i+1] = xstrdup(argv[i]);
   newargz[argc+1] = NULL;
 
   for (i=0; i<argc+1; i++)
   {
-    DEBUG("(main) newargz[%d]   : %s\n",i,newargz[i]);
-    ;
+    LTWRAPPER_DEBUGPRINTF("(main) newargz[%d]   : %s\n",i,newargz[i]);
   }
 
 EOF
@@ -2539,14 +2656,14 @@ EOF
            case $host_os in
              mingw*)
                cat <<EOF
-  execv("$SHELL",(char const **)newargz);
+  execv ("$lt_newargv0", (const char * const *) newargz);
 EOF
-             ;;
+               ;;
              *)
                cat <<EOF
-  execv("$SHELL",newargz);
+  execv ("$lt_newargv0", newargz);
 EOF
-             ;;
+               ;;
            esac
 
            cat <<"EOF"
@@ -2592,7 +2709,7 @@ check_executable(const char * path)
 {
   struct stat st;
 
-  DEBUG("(check_executable)  : %s\n", path ? (*path ? path : "EMPTY!") : "NULL!");
+  LTWRAPPER_DEBUGPRINTF("(check_executable)  : %s\n", path ? (*path ? path : "EMPTY!") : "NULL!");
   if ((!path) || (!*path))
     return 0;
 
@@ -2612,8 +2729,37 @@ check_executable(const char * path)
     return 0;
 }
 
+int
+make_executable(const char * path)
+{
+  int rval = 0;
+  struct stat st;
+
+  /* MinGW & native WIN32 do not support S_IXOTH or S_IXGRP */
+  int S_XFLAGS = 
+#if defined (S_IXOTH)
+       S_IXOTH ||
+#endif
+#if defined (S_IXGRP)
+       S_IXGRP ||
+#endif
+       S_IXUSR;
+
+    LTWRAPPER_DEBUGPRINTF("(make_executable)  : %s\n", path ? (*path ? path : "EMPTY!") : "NULL!");
+    if ((!path) || (!*path))
+        return 0;
+
+    if (stat (path, &st) >= 0)
+    {
+        rval = chmod ( path, st.st_mode | S_XFLAGS );
+    }
+    return rval;
+}
+
 /* Searches for the full path of the wrapper.  Returns
-   newly allocated full path name if found, NULL otherwise */
+   newly allocated full path name if found, NULL otherwise
+   Does not chase symlinks, even on platforms that support them.
+*/
 char *
 find_executable (const char* wrapper)
 {
@@ -2625,7 +2771,7 @@ find_executable (const char* wrapper)
   int tmp_len;
   char* concat_name;
 
-  DEBUG("(find_executable)  : %s\n", wrapper ? (*wrapper ? wrapper : "EMPTY!") : "NULL!");
+  LTWRAPPER_DEBUGPRINTF("(find_executable)  : %s\n", wrapper ? (*wrapper ? wrapper : "EMPTY!") : "NULL!");
 
   if ((wrapper == NULL) || (*wrapper == '\0'))
     return NULL;
@@ -2714,6 +2860,62 @@ find_executable (const char* wrapper)
   return NULL;
 }
 
+char *
+chase_symlinks(const char *pathspec)
+{
+#ifndef S_ISLNK
+    return xstrdup ( pathspec );
+#else
+    char buf[LT_PATHMAX];
+    struct stat s;
+    int rv = 0;
+    char* tmp_pathspec = xstrdup (pathspec);
+    char* p;
+    int has_symlinks = 0;
+    while (strlen(tmp_pathspec) && !has_symlinks)
+    {
+        LTWRAPPER_DEBUGPRINTF("checking path component for symlinks: %s\n", tmp_pathspec);
+        if (lstat (tmp_pathspec, &s) == 0)
+        {
+            if (S_ISLNK(s.st_mode) != 0)
+            {
+                has_symlinks = 1;
+                break;
+            }
+
+            /* search backwards for last DIR_SEPARATOR */
+            p = tmp_pathspec + strlen(tmp_pathspec) - 1;
+            while ( (p > tmp_pathspec) && (! IS_DIR_SEPARATOR(*p)) )
+                p--;
+            if ( (p == tmp_pathspec) && (! IS_DIR_SEPARATOR(*p)) )
+            {
+                /* no more DIR_SEPARATORS left */
+                break;
+            }
+            *p = '\0';
+        }
+        else
+        {
+            char* errstr = strerror(errno);
+            lt_fatal("Error accessing file %s (%s)", tmp_pathspec, errstr);
+        }
+    }
+    XFREE(tmp_pathspec);
+
+    if (!has_symlinks)
+    {
+       return xstrdup ( pathspec );
+    } 
+
+    tmp_pathspec = realpath ( pathspec, buf );
+    if (tmp_pathspec == 0)
+    {
+        lt_fatal("Could not follow symlinks for %s", pathspec);
+    }
+    return xstrdup ( tmp_pathspec );
+#endif
+}
+
 char *
 strendzap(char *str, const char *pat)
 {