diff --git a/libltdl/config/ltmain.m4sh b/libltdl/config/ltmain.m4sh index 80a1ff3..cb0672b 100644 --- a/libltdl/config/ltmain.m4sh +++ b/libltdl/config/ltmain.m4sh @@ -2727,10 +2727,6 @@ func_emit_cwrapperexe_src () 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* "$SHELL $output", - but could eventually absorb all of the scripts functionality and - exec $objdir/$outputname directly. */ EOF cat <<"EOF" @@ -2855,22 +2851,13 @@ int setenv (const char *, const char *, int); if (stale) { free ((void *) stale); stale = 0; } \ } while (0) -#undef LTWRAPPER_DEBUGPRINTF -#if defined LT_DEBUGWRAPPER -# define LTWRAPPER_DEBUGPRINTF(args) ltwrapper_debugprintf args -static void -ltwrapper_debugprintf (const char *fmt, ...) -{ - va_list args; - va_start (args, fmt); - (void) vfprintf (stderr, fmt, args); - va_end (args); -} +#if defined(LT_DEBUGWRAPPER) +static int lt_debug = 1; #else -# define LTWRAPPER_DEBUGPRINTF(args) +static int lt_debug = 0; #endif -const char *program_name = NULL; +const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ void *xmalloc (size_t num); char *xstrdup (const char *string); @@ -2880,7 +2867,10 @@ 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, ...); +void lt_debugprintf (const char *file, int line, const char *fmt, ...); +void lt_fatal (const char *file, int line, const char *message, ...); +static const char *nonnull (const char *s); +static const char *nonempty (const char *s); 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_update_exe_path (const char *name, const char *value); @@ -2932,12 +2922,10 @@ EOF cat <<"EOF" #define LTWRAPPER_OPTION_PREFIX "--lt-" -#define LTWRAPPER_OPTION_PREFIX_LENGTH 5 -static const size_t opt_prefix_len = LTWRAPPER_OPTION_PREFIX_LENGTH; static const char *ltwrapper_option_prefix = LTWRAPPER_OPTION_PREFIX; - static const char *dumpscript_opt = LTWRAPPER_OPTION_PREFIX "dump-script"; +static const char *debug_opt = LTWRAPPER_OPTION_PREFIX "debug"; int main (int argc, char *argv[]) @@ -2954,10 +2942,13 @@ main (int argc, char *argv[]) int i; program_name = (char *) xstrdup (base_name (argv[0])); - LTWRAPPER_DEBUGPRINTF (("(main) argv[0] : %s\n", argv[0])); - LTWRAPPER_DEBUGPRINTF (("(main) program_name : %s\n", program_name)); + newargz = XMALLOC (char *, argc + 1); - /* very simple arg parsing; don't want to rely on getopt */ + /* very simple arg parsing; don't want to rely on getopt + * also, copy all non cwrapper options to newargz, except + * argz[0], which is handled differently + */ + newargc=0; for (i = 1; i < argc; i++) { if (strcmp (argv[i], dumpscript_opt) == 0) @@ -2974,21 +2965,54 @@ EOF lt_dump_script (stdout); return 0; } + if (strcmp (argv[i], debug_opt) == 0) + { + lt_debug = 1; + continue; + } + if (strcmp (argv[i], ltwrapper_option_prefix) == 0) + { + /* however, if there is an option in the LTWRAPPER_OPTION_PREFIX + namespace, but it is not one of the ones we know about and + have already dealt with, above (inluding dump-script), then + report an error. Otherwise, targets might begin to believe + they are allowed to use options in the LTWRAPPER_OPTION_PREFIX + namespace. The first time any user complains about this, we'll + need to make LTWRAPPER_OPTION_PREFIX a configure-time option + or a configure.ac-settable value. + */ + lt_fatal (__FILE__, __LINE__, + "unrecognized %s option: '%s'", + ltwrapper_option_prefix, argv[i]); + } + /* otherwise ... */ + newargz[++newargc] = xstrdup (argv[i]); } + newargz[++newargc] = NULL; + +EOF + cat <"))); + lt_debugprintf (__FILE__, __LINE__, "(main) lt_argv_zero: %s\n", + nonnull (lt_argv_zero)); for (i = 0; i < newargc; i++) { - LTWRAPPER_DEBUGPRINTF (("(main) newargz[%d] : %s\n", i, (newargz[i] ? newargz[i] : ""))); + lt_debugprintf (__FILE__, __LINE__, "(main) newargz[%d]: %s\n", + i, nonnull (newargz[i])); } EOF @@ -3099,7 +3104,9 @@ EOF if (rval == -1) { /* failed to start process */ - LTWRAPPER_DEBUGPRINTF (("(main) failed to launch target \"%s\": errno = %d\n", lt_argv_zero, errno)); + lt_debugprintf (__FILE__, __LINE__, + "(main) failed to launch target \"%s\": %s\n", + lt_argv_zero, strerror (errno)); return 127; } return rval; @@ -3121,7 +3128,7 @@ xmalloc (size_t num) { void *p = (void *) malloc (num); if (!p) - lt_fatal ("Memory exhausted"); + lt_fatal (__FILE__, __LINE__, "memory exhausted"); return p; } @@ -3155,8 +3162,8 @@ check_executable (const char *path) { struct stat st; - LTWRAPPER_DEBUGPRINTF (("(check_executable) : %s\n", - path ? (*path ? path : "EMPTY!") : "NULL!")); + lt_debugprintf (__FILE__, __LINE__, "(check_executable): %s\n", + nonempty (path)); if ((!path) || (!*path)) return 0; @@ -3173,8 +3180,8 @@ make_executable (const char *path) int rval = 0; struct stat st; - LTWRAPPER_DEBUGPRINTF (("(make_executable) : %s\n", - path ? (*path ? path : "EMPTY!") : "NULL!")); + lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", + nonempty (path)); if ((!path) || (!*path)) return 0; @@ -3200,8 +3207,8 @@ find_executable (const char *wrapper) int tmp_len; char *concat_name; - LTWRAPPER_DEBUGPRINTF (("(find_executable) : %s\n", - wrapper ? (*wrapper ? wrapper : "EMPTY!") : "NULL!")); + lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", + nonempty (wrapper)); if ((wrapper == NULL) || (*wrapper == '\0')) return NULL; @@ -3254,7 +3261,8 @@ find_executable (const char *wrapper) { /* empty path: current directory */ if (getcwd (tmp, LT_PATHMAX) == NULL) - lt_fatal ("getcwd failed"); + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + strerror (errno)); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); @@ -3279,7 +3287,7 @@ find_executable (const char *wrapper) } /* Relative path | not found in path: prepend cwd */ if (getcwd (tmp, LT_PATHMAX) == NULL) - lt_fatal ("getcwd failed"); + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", strerror (errno)); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); @@ -3305,8 +3313,9 @@ chase_symlinks (const char *pathspec) int has_symlinks = 0; while (strlen (tmp_pathspec) && !has_symlinks) { - LTWRAPPER_DEBUGPRINTF (("checking path component for symlinks: %s\n", - tmp_pathspec)); + lt_debugprintf (__FILE__, __LINE__, + "checking path component for symlinks: %s\n", + tmp_pathspec); if (lstat (tmp_pathspec, &s) == 0) { if (S_ISLNK (s.st_mode) != 0) @@ -3328,8 +3337,9 @@ chase_symlinks (const char *pathspec) } else { - char *errstr = strerror (errno); - lt_fatal ("Error accessing file %s (%s)", tmp_pathspec, errstr); + lt_fatal (__FILE__, __LINE__, + "error accessing file \"%s\": %s", + tmp_pathspec, strerror (errno)); } } XFREE (tmp_pathspec); @@ -3342,7 +3352,8 @@ chase_symlinks (const char *pathspec) tmp_pathspec = realpath (pathspec, buf); if (tmp_pathspec == 0) { - lt_fatal ("Could not follow symlinks for %s", pathspec); + lt_fatal (__FILE__, __LINE__, + "could not follow symlinks for %s", pathspec); } return xstrdup (tmp_pathspec); #endif @@ -3368,11 +3379,25 @@ strendzap (char *str, const char *pat) return str; } +void +lt_debugprintf (const char *file, int line, const char *fmt, ...) +{ + va_list args; + if (lt_debug) + { + (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); + va_start (args, fmt); + (void) vfprintf (stderr, fmt, args); + va_end (args); + } +} + static void -lt_error_core (int exit_status, const char *mode, +lt_error_core (int exit_status, const char *file, + int line, const char *mode, const char *message, va_list ap) { - fprintf (stderr, "%s: %s: ", program_name, mode); + fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); vfprintf (stderr, message, ap); fprintf (stderr, ".\n"); @@ -3381,20 +3406,32 @@ lt_error_core (int exit_status, const char *mode, } void -lt_fatal (const char *message, ...) +lt_fatal (const char *file, int line, const char *message, ...) { va_list ap; va_start (ap, message); - lt_error_core (EXIT_FAILURE, "FATAL", message, ap); + lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); va_end (ap); } +static const char * +nonnull (const char *s) +{ + return s ? s : "(null)"; +} + +static const char * +nonempty (const char *s) +{ + return (s && !*s) ? "(empty)" : nonnull (s); +} + void lt_setenv (const char *name, const char *value) { - LTWRAPPER_DEBUGPRINTF (("(lt_setenv) setting '%s' to '%s'\n", - (name ? name : ""), - (value ? value : ""))); + lt_debugprintf (__FILE__, __LINE__, + "(lt_setenv) setting '%s' to '%s'\n", + nonnull (name), nonnull (value)); { #ifdef HAVE_SETENV /* always make a copy, for consistency with !HAVE_SETENV */ @@ -3442,9 +3479,9 @@ lt_extend_str (const char *orig_value, const char *add, int to_end) 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 : ""))); + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); if (name && *name && value && *value) { @@ -3463,9 +3500,9 @@ lt_update_exe_path (const char *name, const char *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 : ""))); + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); if (name && *name && value && *value) { diff --git a/tests/cwrapper.at b/tests/cwrapper.at index 42f8d0f..babd91e 100644 --- a/tests/cwrapper.at +++ b/tests/cwrapper.at @@ -79,5 +79,58 @@ for restrictive_flags in '-Wall -Werror' '-std=c89 -Wall -Werror' '-std=c99 -Wal LT_AT_EXEC_CHECK([./usea], [0], [ignore], [ignore], []) done + +# Test run-time activation of wrapper debugging. +# This is not part of the loop above, because we +# need to check, not ignore, the output. +CFLAGS="$orig_CFLAGS" +LIBTOOL=$orig_LIBTOOL + +AT_CHECK([$LIBTOOL --mode=compile $CC $CPPFLAGS $CFLAGS -c liba.c], + [], [ignore], [ignore]) +AT_CHECK([$LIBTOOL --mode=link $CC $CFLAGS $LDFLAGS -no-undefined -o liba.la -rpath /foo liba.lo], + [], [ignore], [ignore]) +AT_CHECK([test -f liba.la]) + +AT_CHECK([$CC $CPPFLAGS $CFLAGS -c usea.c], + [], [ignore], [ignore]) +AT_CHECK([$LIBTOOL --mode=link $CC $CFLAGS $LDFLAGS -o usea$EXEEXT usea.$OBJEXT liba.la], + [], [ignore], [ignore]) +LT_AT_EXEC_CHECK([./usea], [0], [ignore], [stderr], [--lt-debug]) +LT_AT_UNIFY_NL([stderr]) +AT_CHECK([grep 'libtool wrapper' stderr], [0], [ignore], [ignore]) + + +# Test compile-time activation of wrapper debugging. +# We structure this test as a loop, so that we can 'break' out of it +# if necessary -- even though the loop by design executes only once. +for debugwrapper_flags in '-DLT_DEBUGWRAPPER'; do + CFLAGS="$orig_CFLAGS $debugwrapper_flags" + sed -e "s/LTCFLAGS=.*/&' $debugwrapper_flags'/" \ + -e "s/^lt_option_debug=/lt_option_debug=1/" \ + < "$orig_LIBTOOL" > ./libtool + LIBTOOL=./libtool + + # make sure $debugwrapper_flags do not cause a failure + # themselves (e.g. because a non-gcc compiler doesn't + # understand them) + $LIBTOOL --mode=compile $CC $CPPFLAGS $CFLAGS -c trivial.c || continue + + AT_CHECK([$LIBTOOL --mode=compile $CC $CPPFLAGS $CFLAGS -c liba.c], + [], [ignore], [ignore]) + AT_CHECK([$LIBTOOL --mode=link $CC $CFLAGS $LDFLAGS -no-undefined -o liba.la -rpath /foo liba.lo], + [], [ignore], [ignore]) + AT_CHECK([test -f liba.la]) + + AT_CHECK([$CC $CPPFLAGS $CFLAGS -c usea.c], + [], [ignore], [ignore]) + AT_CHECK([$LIBTOOL --mode=link $CC $CFLAGS $LDFLAGS -o usea$EXEEXT usea.$OBJEXT liba.la], + [], [ignore], [ignore]) + LT_AT_EXEC_CHECK([./usea], [0], [ignore], [stderr], []) + LT_AT_UNIFY_NL([stderr]) + AT_CHECK([grep 'libtool wrapper' stderr], [0], [ignore], [ignore]) +done + + AT_CLEANUP