[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH] [mingw|cygwin] Modify cwrapper to invoke target directly.
From: |
Charles Wilson |
Subject: |
[PATCH] [mingw|cygwin] Modify cwrapper to invoke target directly. |
Date: |
Mon, 5 May 2008 20:23:05 -0400 |
2008-05-05 Charles Wilson <...>
* libltdl/config/ltmain.m4sh (func_to_native_path):
new function. If $host is mingw, and $build is mingw
or cygwin, convert path to mingw native format.
(func_to_native_pathlist): new function. Ditto, for
:-separated pathlists.
(func_emit_cwrapperexe_src) [__CYGWIN__ && __STRICT_ANSI__]:
ensure putenv and setenv are declared. Define HAVE_SETENV.
(func_emit_cwrapperexe_src) [main]: add new constants to
hold desired PATH settings; initialize and convert to native
mingw format using functions above. Add new command-line
options --lt-env-set, --lt-env-prepend, and --lt-env-append.
No longer emit wrapper script as integral part of launching
child. Remove support for (now) unnecessary $TARGETSHELL.
Exec actual target executable directly.
(func_emit_cwrapperexe_src) [lt_setenv]: new function.
(func_emit_cwrapperexe_src) [lt_extend_str]: new function.
(func_emit_cwrapperexe_src) [lt_split_name_value]: new function.
(func_emit_cwrapperexe_src) [lt_opt_process_env_set]: new function.
(func_emit_cwrapperexe_src) [lt_opt_process_env_prepend]: new function.
(func_emit_cwrapperexe_src) [lt_opt_process_env_append]: new function.
(func_emit_cwrapperexe_src) [lt_update_exe_path]: new function.
(func_emit_cwrapperexe_src) [lt_update_lib_path]: new function.
---
Resubmission of
http://lists.gnu.org/archive/html/libtool-patches/2008-04/msg00164.html rebased
against current master.
Note that this version does not yet allow for *nix-build->mingw-host cross
compiles. That requires additional changes outlined in the third attachment to
the mailing-group post specified above. I'll address that as a follow-on
patch, once this one has been vetted.
I'm sorta thinking I should rename the func_to_native* functions s/native/host/
?
Comments, questions?
libltdl/config/ltmain.m4sh | 472 +++++++++++++++++++++++++++++++++++++-------
1 files changed, 400 insertions(+), 72 deletions(-)
diff --git a/libltdl/config/ltmain.m4sh b/libltdl/config/ltmain.m4sh
index 33689b9..82f920e 100644
--- a/libltdl/config/ltmain.m4sh
+++ b/libltdl/config/ltmain.m4sh
@@ -2247,8 +2247,6 @@ func_extract_archives ()
func_extract_archives_result="$my_oldobjs"
}
-
-
# func_emit_wrapper arg
#
# emit a libtool wrapper script on stdout
@@ -2474,6 +2472,106 @@ fi\
}
# end: func_emit_wrapper
+# func_to_native_path
+#
+# intended for use on "native" mingw (where libtool itself
+# is running under the msys shell). Paths need to be converted
+# to native format when used with native tools. Ordinarily, the
+# (msys) shell automatically converts such things for non-msys
+# applications it launches, but that isn't available from inside
+# the cwrapper. Similar accommodations are necessary for $host
+# mingw and $build cygwin. Calling this function does no harm
+# on other $build or for other $host.
+func_to_native_path ()
+{
+ func_to_native_path_result="$1"
+ if test -n "$1" ; then
+ case $host in
+ *mingw* )
+ lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g'
+ case $build in
+ *mingw* ) # actually, msys
+ # awkward: cmd appends spaces to result
+ lt_sed_strip_trailing_spaces="s/[ ]*\$//"
+ func_to_native_path_tmp1=`( cmd //c echo "$1" | $SED -e
"$lt_sed_strip_trailing_spaces" ) 2>/dev/null || echo ""`
+ func_to_native_path_result=`echo "$func_to_native_path_tmp1" |
$SED -e "$lt_sed_naive_backslashify"`
+ ;;
+ *cygwin* )
+ func_to_native_path_tmp1=`cygpath -w "$1"`
+ func_to_native_path_result=`echo "$func_to_native_path_tmp1" |
$SED -e "$lt_sed_naive_backslashify"`
+ ;;
+ esac
+ if test -z "$func_to_native_path_result" ; then
+ func_error "Could not determine native path corresponding to"
+ func_error " '$1'"
+ func_error "Perhaps it doesn't exist."
+ func_error "Continuing, but running uninstalled executables may not
work."
+ fi
+ ;;
+ esac
+ fi
+}
+# end: func_to_native_path
+
+# func_to_native_pathlist
+#
+# see func_to_native_path, above
+# path separators are also converted from ':' to ';'
+# and if $1 begins or ends with a ':' it is preserved (as ';')
+# on output. This description applies only when $build is
+# mingw (msys) or cygwin, and $host is mingw.
+func_to_native_pathlist ()
+{
+ func_to_native_pathlist_result="$1"
+ if test -n "$1" ; then
+ case $host in
+ *mingw* )
+ lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g'
+ case $build in
+ *mingw* | *cygwin* )
+ # remove leading and trailing ':' from $1. msys behavior is
+ # inconsistent here, and cygpath turns them into into '.;' and ';.'
+ func_to_native_pathlist_tmp1="$1"
+ func_to_native_pathlist_tmp2=`echo "$func_to_native_pathlist_tmp1"
| $SED -e 's|^:*||'`
+ func_to_native_pathlist_tmp1=`echo "$func_to_native_pathlist_tmp2"
| $SED -e 's|:*$||'`
+ ;;
+ esac
+ case $build in
+ *mingw* ) # actually, msys
+ # awkward: cmd appends spaces to result
+ lt_sed_strip_trailing_spaces="s/[ ]*\$//"
+ func_to_native_pathlist_tmp2=`( cmd //c echo
"$func_to_native_pathlist_tmp1" |\
+ $SED -e "$lt_sed_strip_trailing_spaces" ) 2>/dev/null || echo ""`
+ func_to_native_pathlist_result=`echo
"$func_to_native_pathlist_tmp2" | $SED -e "$lt_sed_naive_backslashify"`
+ ;;
+ *cygwin* )
+ func_to_native_pathlist_tmp2=`cygpath -w -p
"$func_to_native_pathlist_tmp1"`
+ func_to_native_pathlist_result=`echo
"$func_to_native_pathlist_tmp2" | $SED -e "$lt_sed_naive_backslashify"`
+ ;;
+ esac
+ if test -z "$func_to_native_pathlist_result" ; then
+ func_error "Could not determine the native path(s) corresponding to"
+ func_error " '$1'"
+ func_error "perhaps one or more of the paths do not exit."
+ func_error "Continuing, but running uninstalled executables may not
work."
+ fi
+ case $build in
+ *mingw* | *cygwin* )
+ # Now, add the leading and trailing ':' back
+ case "$1" in
+ :* )
func_to_native_pathlist_result=";$func_to_native_pathlist_result" ;;
+ esac
+ case "$1" in
+ *: )
func_to_native_pathlist_result="$func_to_native_pathlist_result;" ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ fi
+}
+# end: func_to_native_pathlist
+
# func_emit_cwrapperexe_src
# emit the source code for a wrapper executable on stdout
# Must ONLY be called from within func_mode_link because
@@ -2509,6 +2607,11 @@ EOF
# include <stdint.h>
# ifdef __CYGWIN__
# include <io.h>
+# define HAVE_SETENV
+# ifdef __STRICT_ANSI__
+int putenv (char *);
+int setenv (const char *, const char *, int);
+# endif
# endif
#endif
#include <malloc.h>
@@ -2615,6 +2718,14 @@ 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, ...);
+void lt_setenv (const char *name, const char *value);
+char *lt_extend_str (const char *orig_value, const char *add, int to_end);
+void lt_opt_process_env_set (const char *arg);
+void lt_opt_process_env_prepend (const char *arg);
+void lt_opt_process_env_append (const char *arg);
+int lt_split_name_value (const char *arg, char** name, char** value);
+void lt_update_exe_path (const char *name, const char *value);
+void lt_update_lib_path (const char *name, const char *value);
static const char *script_text =
EOF
@@ -2626,18 +2737,53 @@ EOF
cat <<EOF
const char * MAGIC_EXE = "$magic_exe";
+const char * LIB_PATH_VARNAME = "$shlibpath_var";
+EOF
+
+ if test "$shlibpath_overrides_runpath" = yes && test -n
"$shlibpath_var" && test -n "$temp_rpath"; then
+ func_to_native_pathlist "$temp_rpath"
+ cat <<EOF
+const char * LIB_PATH_VALUE = "$func_to_native_pathlist_result";
+EOF
+ else
+ cat <<"EOF"
+const char * LIB_PATH_VALUE = "";
+EOF
+ fi
+
+ if test -n "$dllsearchpath"; then
+ func_to_native_pathlist "$dllsearchpath:"
+ cat <<EOF
+const char * EXE_PATH_VARNAME = "PATH";
+const char * EXE_PATH_VALUE = "$func_to_native_pathlist_result";
+EOF
+ else
+ cat <<"EOF"
+const char * EXE_PATH_VARNAME = "";
+const char * EXE_PATH_VALUE = "";
+EOF
+ fi
+
+ cat <<"EOF"
+
+static const char *dumpscript_opt = "--lt-dump-script";
+static const char *env_set_opt = "--lt-env-set";
+ /* argument is putenv-style "foo=bar", value of foo is set to bar */
+static const char *env_prepend_opt = "--lt-env-prepend";
+ /* argument is putenv-style "foo=bar", new value of foo is bar${foo} */
+static const char *env_append_opt = "--lt-env-append";
+ /* argument is putenv-style "foo=bar", new value of foo is ${foo}bar */
int
main (int argc, char *argv[])
{
char **newargz;
+ int newargc;
char *tmp_pathspec;
char *actual_cwrapper_path;
- char *shwrapper_name;
+ char *target_name;
intptr_t rval = 127;
- FILE *shwrapper;
- const char *dumpscript_opt = "--lt-dump-script";
int i;
program_name = (char *) xstrdup (base_name (argv[0]));
@@ -2657,38 +2803,13 @@ EOF
;;
esac
- cat <<EOF
+ cat <<"EOF"
printf ("%s", script_text);
return 0;
}
}
- newargz = XMALLOC (char *, argc + 2);
-EOF
-
- 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 = XMALLOC (char *, argc + 1);
tmp_pathspec = find_executable (argv[0]);
if (tmp_pathspec == NULL)
lt_fatal ("Couldn't find %s", argv[0]);
@@ -2700,39 +2821,38 @@ EOF
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 ("_ltshwrapperTMP") + 1));
- strcpy (tmp_pathspec, shwrapper_name);
- strcat (tmp_pathspec, "_ltshwrapperTMP");
- XFREE (shwrapper_name);
- shwrapper_name = tmp_pathspec;
+ target_name = (char *) xstrdup (base_name (actual_cwrapper_path));
+ strendzap (actual_cwrapper_path, target_name);
+
+ /* target_name transforms */
+ strendzap (target_name, ".exe");
+ tmp_pathspec = XMALLOC (char, (strlen (target_name) +
+ strlen (".exe") + 1));
+ strcpy (tmp_pathspec, target_name);
+ strcat (tmp_pathspec, ".exe");
+ XFREE (target_name);
+ target_name = tmp_pathspec;
tmp_pathspec = 0;
- LTWRAPPER_DEBUGPRINTF (("(main) libtool shell wrapper name: %s\n",
- shwrapper_name));
+ LTWRAPPER_DEBUGPRINTF (("(main) libtool target name: %s\n",
+ target_name));
EOF
cat <<EOF
- newargz[1] =
+ newargz[0] =
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);
+ strlen ("$objdir") + 1 + strlen (target_name) + 1));
+ strcpy (newargz[0], actual_cwrapper_path);
+ strcat (newargz[0], "$objdir");
+ strcat (newargz[0], "/");
+ strcat (newargz[0], target_name);
EOF
-
case $host_os in
mingw*)
cat <<"EOF"
{
char* p;
- while ((p = strchr (newargz[1], '\\')) != NULL)
+ while ((p = strchr (newargz[0], '\\')) != NULL)
{
*p = '/';
}
@@ -2742,39 +2862,77 @@ EOF
esac
cat <<"EOF"
- XFREE (shwrapper_name);
+ XFREE (target_name);
XFREE (actual_cwrapper_path);
- /* always write in binary mode */
- if ((shwrapper = fopen (newargz[1], FOPEN_WB)) == 0)
- {
- lt_fatal ("Could not open %s for writing", newargz[1]);
- }
- fprintf (shwrapper, "%s", script_text);
- fclose (shwrapper);
-
- make_executable (newargz[1]);
+ lt_setenv ("BIN_SH", "xpg4"); /* for Tru64 */
+ lt_setenv ("DUALCASE", "1"); /* for MSK sh */
+ lt_update_lib_path (LIB_PATH_VARNAME, LIB_PATH_VALUE);
+ lt_update_exe_path (EXE_PATH_VARNAME, EXE_PATH_VALUE);
+ newargc=0;
for (i = 1; i < argc; i++)
- newargz[i + 1] = xstrdup (argv[i]);
- newargz[argc + 1] = NULL;
+ {
+ if (strcmp (argv[i], env_set_opt) == 0)
+ {
+ if (i+1 < argc)
+ {
+ lt_opt_process_env_set (argv[i+1]);
+ i++; /* don't copy */
+ }
+ else
+ {
+ lt_fatal ("%s missing required argument", env_set_opt);
+ }
+ continue;
+ }
+ if (strcmp (argv[i], env_prepend_opt) == 0)
+ {
+ if (i+1 < argc)
+ {
+ lt_opt_process_env_prepend (argv[i+1]);
+ i++; /* don't copy */
+ }
+ else
+ {
+ lt_fatal ("%s missing required argument", env_prepend_opt);
+ }
+ continue;
+ }
+ if (strcmp (argv[i], env_append_opt) == 0)
+ {
+ if (i+1 < argc)
+ {
+ lt_opt_process_env_append (argv[i+1]);
+ i++; /* don't copy */
+ }
+ else
+ {
+ lt_fatal ("%s missing required argument", env_append_opt);
+ }
+ continue;
+ }
+ /* otherwise ... */
+ newargz[++newargc] = xstrdup (argv[i]);
+ }
+ newargz[++newargc] = NULL;
- for (i = 0; i < argc + 1; i++)
+ for (i = 0; i < newargc; i++)
{
- LTWRAPPER_DEBUGPRINTF (("(main) newargz[%d] : %s\n", i, newargz[i]));
+ LTWRAPPER_DEBUGPRINTF (("(main) newargz[%d] : %s\n", i, (newargz[i] ?
newargz[i] : "<NULL>")));
}
EOF
case $host_os in
mingw*)
- cat <<EOF
+ cat <<"EOF"
/* execv doesn't actually work on mingw as expected on unix */
- rval = _spawnv (_P_WAIT, "$lt_newargv0", (const char * const *) newargz);
+ rval = _spawnv (_P_WAIT, newargz[0], (const char * const *) newargz);
if (rval == -1)
{
/* failed to start process */
- LTWRAPPER_DEBUGPRINTF (("(main) failed to launch target
\"$lt_newargv0\": errno = %d\n", errno));
+ LTWRAPPER_DEBUGPRINTF (("(main) failed to launch target \"%s\": errno =
%d\n", newargz[0], errno));
return 127;
}
return rval;
@@ -2782,8 +2940,8 @@ EOF
EOF
;;
*)
- cat <<EOF
- execv ("$lt_newargv0", newargz);
+ cat <<"EOF"
+ execv (newargz[0], newargz);
return rval; /* =127, but avoids unused variable warning */
}
EOF
@@ -3064,6 +3222,176 @@ lt_fatal (const char *message, ...)
lt_error_core (EXIT_FAILURE, "FATAL", message, ap);
va_end (ap);
}
+
+void
+lt_setenv (const char *name, const char *value)
+{
+ LTWRAPPER_DEBUGPRINTF (("(lt_setenv) setting '%s' to '%s'\n",
+ (name ? name : "<NULL>"),
+ (value ? value : "<NULL>")));
+ {
+#ifdef HAVE_SETENV
+ /* always make a copy, for consistency with !HAVE_SETENV */
+ char *str = xstrdup (value);
+ setenv (name, str, 1);
+#else
+ int len = strlen (name) + 1 + strlen (value) + 1;
+ char *str = XMALLOC (char, len);
+ sprintf (str, "%s=%s", name, value);
+ if (putenv (str) != EXIT_SUCCESS)
+ {
+ XFREE (str);
+ }
+#endif
+ }
+}
+
+char *
+lt_extend_str (const char *orig_value, const char *add, int to_end)
+{
+ char *new_value;
+ if (orig_value && *orig_value)
+ {
+ int len = strlen (add) + strlen (orig_value) + 1;
+ new_value = XMALLOC (char, len);
+ if (to_end)
+ {
+ strcpy (new_value, orig_value);
+ strcat (new_value, add);
+ }
+ else
+ {
+ strcpy (new_value, add);
+ strcat (new_value, orig_value);
+ }
+ }
+ else
+ {
+ new_value = xstrdup (add);
+ }
+ return new_value;
+}
+
+int
+lt_split_name_value (const char *arg, char** name, char** value)
+{
+ const char *p;
+ int len;
+ if (!arg || !*arg)
+ return 1;
+
+ p = strchr (arg, (int)'=');
+
+ if (!p)
+ return 1;
+
+ *value = xstrdup (++p);
+
+ len = strlen (arg) - strlen (*value);
+ *name = XMALLOC (char, len);
+ strncpy (*name, arg, len-1);
+ (*name)[len-1] = '\0';
+
+ return 0;
+}
+
+void
+lt_opt_process_env_set (const char *arg)
+{
+ char *name = NULL;
+ char *value = NULL;
+
+ if (lt_split_name_value (arg, &name, &value) != 0)
+ {
+ XFREE (name);
+ XFREE (value);
+ lt_fatal ("bad argument for %s: '%s'", env_set_opt, arg);
+ }
+
+ lt_setenv (name, value);
+ XFREE (name);
+ XFREE (value);
+}
+
+void
+lt_opt_process_env_prepend (const char *arg)
+{
+ char *name = NULL;
+ char *value = NULL;
+ char *new_value = NULL;
+
+ if (lt_split_name_value (arg, &name, &value) != 0)
+ {
+ XFREE (name);
+ XFREE (value);
+ lt_fatal ("bad argument for %s: '%s'", env_prepend_opt, arg);
+ }
+
+ new_value = lt_extend_str (getenv (name), value, 0);
+ lt_setenv (name, new_value);
+ XFREE (new_value);
+ XFREE (name);
+ XFREE (value);
+}
+
+void
+lt_opt_process_env_append (const char *arg)
+{
+ char *name = NULL;
+ char *value = NULL;
+ char *new_value = NULL;
+
+ if (lt_split_name_value (arg, &name, &value) != 0)
+ {
+ XFREE (name);
+ XFREE (value);
+ lt_fatal ("bad argument for %s: '%s'", env_append_opt, arg);
+ }
+
+ new_value = lt_extend_str (getenv (name), value, 1);
+ lt_setenv (name, new_value);
+ XFREE (new_value);
+ XFREE (name);
+ XFREE (value);
+}
+
+void
+lt_update_exe_path (const char *name, const char *value)
+{
+ LTWRAPPER_DEBUGPRINTF (("(lt_update_exe_path) modifying '%s' by prepending
'%s'\n",
+ (name ? name : "<NULL>"),
+ (value ? value : "<NULL>")));
+
+ if (name && *name && value && *value)
+ {
+ char *new_value = lt_extend_str (getenv (name), value, 0);
+ /* some systems can't cope with a ':'-terminated path #' */
+ int len = strlen (new_value);
+ while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR
(new_value[len-1]))
+ {
+ new_value[len-1] = '\0';
+ }
+ lt_setenv (name, new_value);
+ XFREE (new_value);
+ }
+}
+
+void
+lt_update_lib_path (const char *name, const char *value)
+{
+ LTWRAPPER_DEBUGPRINTF (("(lt_update_lib_path) modifying '%s' by prepending
'%s'\n",
+ (name ? name : "<NULL>"),
+ (value ? value : "<NULL>")));
+
+ if (name && *name && value && *value)
+ {
+ char *new_value = lt_extend_str (getenv (name), value, 0);
+ lt_setenv (name, new_value);
+ XFREE (new_value);
+ }
+}
+
+
EOF
}
# end: func_emit_cwrapperexe_src
--
1.5.5.1
- [PATCH] [mingw|cygwin] Modify cwrapper to invoke target directly.,
Charles Wilson <=
Re: [PATCH] [mingw|cygwin] Modify cwrapper to invoke target directly., Ralf Wildenhues, 2008/05/06