From: Charles Wilson Date: Sat, 26 Apr 2008 20:03:50 +0000 (-0400) Subject: [mingw|cygwin] Modify cwrapper to invoke target directly. X-Git-Tag: v2.2.6~42 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=fae94962aa3c36f3cee00a453c2a7d01baaf4ff0;p=thirdparty%2Flibtool.git [mingw|cygwin] Modify cwrapper to invoke target directly. * 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 use functions above to convert to $host format if necessary. 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, lt_extend_str] [lt_split_name_value, lt_opt_process_env_set] [lt_opt_process_env_prepend, lt_opt_process_env_append] [lt_update_exe_path, lt_update_lib_path]: New functions. --- diff --git a/ChangeLog b/ChangeLog index 81f532e77..5bc51f72b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,25 @@ +2008-05-13 Charles Wilson + + [mingw|cygwin] Modify cwrapper to invoke target directly. + * 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 use functions + above to convert to $host format if necessary. 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, lt_extend_str] + [lt_split_name_value, lt_opt_process_env_set] + [lt_opt_process_env_prepend, lt_opt_process_env_append] + [lt_update_exe_path, lt_update_lib_path]: New functions. + 2008-05-11 Charles Wilson Ensure cwrapper compiles without warnings under -std=c99. diff --git a/libltdl/config/ltmain.m4sh b/libltdl/config/ltmain.m4sh index 09dc43413..0bfae76be 100644 --- a/libltdl/config/ltmain.m4sh +++ b/libltdl/config/ltmain.m4sh @@ -2511,6 +2511,122 @@ func_emit_wrapper () } +# func_to_host_path arg +# +# Convert paths to build format when used with build tools. +# Intended for use with "native" mingw (where libtool itself +# is running under the msys shell). 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. +# +# ARG is the path (on $build) that should be converted to +# the proper representation for $host. The result is stored +# in $func_to_host_path_result. +func_to_host_path () +{ + func_to_host_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_host_path_tmp1=`( cmd //c echo "$1" |\ + $SED -e "$lt_sed_strip_trailing_spaces" ) 2>/dev/null || echo ""` + func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\ + $SED -e "$lt_sed_naive_backslashify"` + ;; + *cygwin* ) + func_to_host_path_tmp1=`cygpath -w "$1"` + func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\ + $SED -e "$lt_sed_naive_backslashify"` + ;; + esac + if test -z "$func_to_host_path_result" ; then + func_error "Could not determine host path corresponding to" + func_error " '$1'" + func_error "Continuing, but uninstalled executables may not work." + fi + ;; + esac + fi +} +# end: func_to_host_path + +# func_to_host_pathlist arg +# +# Convert pathlists to build format when used with build tools. +# See func_to_host_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. +# +# ARG is a pathlist (on $build) that should be converted to +# the proper representation on $host. The result is stored +# in $func_to_host_pathlist_result. +func_to_host_pathlist () +{ + func_to_host_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. The behavior of + # msys is inconsistent here, and cygpath turns them into + # into '.;' and ';.' + func_to_host_pathlist_tmp2="$1" + func_to_host_pathlist_tmp1=`echo "$func_to_host_pathlist_tmp2" |\ + $SED -e 's|^:*||' -e 's|:*$||'` + ;; + esac + case $build in + *mingw* ) # Actually, msys. + # Awkward: cmd appends spaces to result. + lt_sed_strip_trailing_spaces="s/[ ]*\$//" + func_to_host_pathlist_tmp2=`( cmd //c echo "$func_to_host_pathlist_tmp1" |\ + $SED -e "$lt_sed_strip_trailing_spaces" ) 2>/dev/null || echo ""` + func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp2" |\ + $SED -e "$lt_sed_naive_backslashify"` + ;; + *cygwin* ) + func_to_host_pathlist_tmp2=`cygpath -w -p "$func_to_host_pathlist_tmp1"` + func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp2" |\ + $SED -e "$lt_sed_naive_backslashify"` + ;; + esac + if test -z "$func_to_host_pathlist_result" ; then + func_error "Could not determine the host path(s) corresponding to" + func_error " '$1'" + func_error "Continuing, but uninstalled executables may not work." + fi + case $build in + *mingw* | *cygwin* ) + # Now, add the leading and trailing ':' back + case "$1" in + :* ) func_to_host_pathlist_result=";$func_to_host_pathlist_result" + ;; + esac + case "$1" in + *: ) func_to_host_pathlist_result="$func_to_host_pathlist_result;" + ;; + esac + ;; + esac + ;; + esac + fi +} +# end: func_to_host_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 @@ -2546,8 +2662,11 @@ EOF # include # ifdef __CYGWIN__ # include +# define HAVE_SETENV # ifdef __STRICT_ANSI__ char *realpath (const char *, char *); +int putenv (char *); +int setenv (const char *, const char *, int); # endif # endif #endif @@ -2655,6 +2774,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_part1 = EOF @@ -2674,18 +2801,72 @@ EOF cat </dev/null || echo $SHELL` - case $lt_newargv0 in - *.exe | *.EXE) ;; - *) lt_newargv0=$lt_newargv0.exe ;; - esac - ;; - * ) lt_newargv0=$SHELL ;; - esac - fi - - cat < env_set_opt_len) && (argv[i][env_set_opt_len] == '=')) + { + const char *p = argv[i] + env_set_opt_len + 1; + lt_opt_process_env_set (p); + } + else if ((arglen == env_set_opt_len) && + (i + 1 < argc) && + (strcmp (argv[i + 1], "--") != 0)) + { + lt_opt_process_env_set (argv[i + 1]); + i++; /* don't copy */ + } + else + lt_fatal ("%s missing required argument", env_set_opt); + continue; + } + if (strncmp (argv[i], env_prepend_opt, env_prepend_opt_len) == 0) + { + if ((arglen > env_prepend_opt_len) && + (argv[i][env_prepend_opt_len] == '=')) + { + const char *p = argv[i] + env_prepend_opt_len + 1; + lt_opt_process_env_prepend (p); + } + else if ((arglen == env_prepend_opt_len) && + (i + 1 < argc) && + (strcmp (argv[i + 1], "--") != 0)) + { + lt_opt_process_env_prepend (argv[i + 1]); + i++; /* don't copy */ + } + else + lt_fatal ("%s missing required argument", env_prepend_opt); + continue; + } + if (strncmp (argv[i], env_append_opt, env_append_opt_len) == 0) + { + if ((arglen > env_append_opt_len) && + (argv[i][env_append_opt_len] == '=')) + { + const char *p = argv[i] + env_append_opt_len + 1; + lt_opt_process_env_append (p); + } + else if ((arglen == env_append_opt_len) && + (i + 1 < argc) && + (strcmp (argv[i + 1], "--") != 0)) + { + lt_opt_process_env_append (argv[i + 1]); + i++; /* don't copy */ + } + else + lt_fatal ("%s missing required argument", env_append_opt); + continue; + } + if (strcmp (argv[i], "--") == 0) + { + /* immediately copy all the rest of the arguments */ + ++i; + for (; i < argc; i++) + newargz[++newargc] = xstrdup (argv[i]); + + /* same as break, because i = argc */ + continue; + } + /* otherwise ... */ + newargz[++newargc] = xstrdup (argv[i]); + } + newargz[++newargc] = NULL; - for (i = 0; i < argc + 1; i++) + LTWRAPPER_DEBUGPRINTF (("(main) lt_argv_zero : %s\n", (lt_argv_zero ? lt_argv_zero : ""))); + 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] : ""))); } EOF case $host_os in mingw*) - cat <"), + (value ? value : ""))); + { +#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 orig_value_len = strlen (orig_value); + int add_len = strlen (add); + new_value = XMALLOC (char, add_len + orig_value_len + 1); + if (to_end) + { + strcpy (new_value, orig_value); + strcpy (new_value + orig_value_len, add); + } + else + { + strcpy (new_value, add); + strcpy (new_value + add_len, 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 : ""), + (value ? value : ""))); + + 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 : ""), + (value ? value : ""))); + + 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 @@ -6910,11 +7325,10 @@ EOF func_emit_cwrapperexe_src > $cwrappersource - # 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. + # The wrapper executable is built using the $host compiler, + # because it contains $host paths and files. If cross- + # compiling, it, like the target executable, must be + # executed on the $host or under an emulation environment. $opt_dry_run || { $LTCC $LTCFLAGS -o $cwrapper $cwrappersource $STRIP $cwrapper