Squashed together and reposted from: http://lists.gnu.org/archive/html/libtool-patches/2009-12/msg00014.html and followon: http://lists.gnu.org/archive/html/libtool-patches/2010-01/msg00047.html
This (combination) was the first of the two patches whose /first/ 72hour rule invocation was here: http://lists.gnu.org/archive/html/libtool-patches/2010-02/msg00003.html Starting a new clock. Test suite history including with the other patch, since they were tested together. No regressions attributable to these changes, on cygwin or mingw. No test failures at all on linux. Consolidated changelog: 2010-02-18 Charles Wilson <...> Enable runtime cwrapper debugging; add tests * libltdl/config/ltmain.m4sh (func_emit_cwrapperexe_src): Update comments. Initialize program_name. Eliminate _LENGTH variables for string constants. In debug mode, print a banner with known content before any other output. Remove LTWRAPPER_DEBUGPRINTF macro. Add constants and variables to support new --lt-debug option. (func_emit_cwrapperexe_src:ltwrapper_debugprintf): Renamed to... (func_emit_cwrapperexe_src:lt_debugprintf): this. Only print messages if lt_debug != 0. Ensure appearance of messages conforms to GCS. (func_emit_cwrapperexe_src:lt_fatal): Ditto. (func_emit_cwrapperexe_src:lt_error_core): Ditto. (func_emit_cwrapperexe_src): Update all callers to lt_fatal. Update all users of LTWRAPPER_DEBUGPRINTF (()) to call lt_debugprintf () directly. (func_emit_cwrapperexe_src:main): Consolidate option parsing. Ensure first use of lt_debugprintf occurs after option parsing. Add stanza to parse for --lt-debug and set lt_debug variable. Use strcmp rather than strncmp, where safe. * tests/cwrapper.at: Add new tests for --lt-debug and -DLT_DEBUGWRAPPER. -- Chuck
diff --git a/libltdl/config/ltmain.m4sh b/libltdl/config/ltmain.m4sh index 80a1ff3..4549023 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 = "wrapper"; /* in case xstrdup fails */ void *xmalloc (size_t num); char *xstrdup (const char *string); @@ -2880,7 +2867,8 @@ 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, ...); 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 +2920,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 +2940,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,18 +2963,51 @@ 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 <<EOF + /* first use of lt_debugprintf AFTER parsing options */ + lt_debugprintf (__FILE__, __LINE__, "libtool wrapper (GNU $PACKAGE$TIMESTAMP) $VERSION\n"); +EOF + cat <<"EOF" + lt_debugprintf (__FILE__, __LINE__, "(main) argv[0]: %s\n", argv[0]); + lt_debugprintf (__FILE__, __LINE__, "(main) program_name: %s\n", program_name); - newargz = XMALLOC (char *, argc + 1); tmp_pathspec = find_executable (argv[0]); if (tmp_pathspec == NULL) - lt_fatal ("Couldn't find %s", argv[0]); - LTWRAPPER_DEBUGPRINTF (("(main) found exe (before symlink chase) at : %s\n", - tmp_pathspec)); + lt_fatal (__FILE__, __LINE__, "Couldn't find %s", argv[0]); + lt_debugprintf (__FILE__, __LINE__, + "(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)); + lt_debugprintf (__FILE__, __LINE__, + "(main) found exe (after symlink chase) at: %s\n", + actual_cwrapper_path); XFREE (tmp_pathspec); actual_cwrapper_name = xstrdup( base_name (actual_cwrapper_path)); @@ -3006,8 +3028,9 @@ EOF target_name = tmp_pathspec; tmp_pathspec = 0; - LTWRAPPER_DEBUGPRINTF (("(main) libtool target name: %s\n", - target_name)); + lt_debugprintf (__FILE__, __LINE__, + "(main) libtool target name: %s\n", + target_name); EOF cat <<EOF @@ -3060,32 +3083,12 @@ EOF 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++) - { - if (strncmp (argv[i], ltwrapper_option_prefix, opt_prefix_len) == 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 ("Unrecognized option in %s namespace: '%s'", - ltwrapper_option_prefix, argv[i]); - } - /* otherwise ... */ - newargz[++newargc] = xstrdup (argv[i]); - } - newargz[++newargc] = NULL; - - LTWRAPPER_DEBUGPRINTF (("(main) lt_argv_zero : %s\n", (lt_argv_zero ? lt_argv_zero : "<NULL>"))); + lt_debugprintf (__FILE__, __LINE__, "(main) lt_argv_zero: %s\n", + (lt_argv_zero ? lt_argv_zero : "<NULL>")); for (i = 0; i < newargc; i++) { - LTWRAPPER_DEBUGPRINTF (("(main) newargz[%d] : %s\n", i, (newargz[i] ? newargz[i] : "<NULL>"))); + lt_debugprintf (__FILE__, __LINE__, "(main) newargz[%d]: %s\n", + i, (newargz[i] ? newargz[i] : "<NULL>")); } EOF @@ -3099,7 +3102,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\": errno = %d\n", + lt_argv_zero, errno); return 127; } return rval; @@ -3121,7 +3126,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 +3160,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", + path ? (*path ? path : "EMPTY!") : "NULL!"); if ((!path) || (!*path)) return 0; @@ -3173,8 +3178,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", + path ? (*path ? path : "EMPTY!") : "NULL!"); if ((!path) || (!*path)) return 0; @@ -3200,8 +3205,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", + wrapper ? (*wrapper ? wrapper : "EMPTY!") : "NULL!"); if ((wrapper == NULL) || (*wrapper == '\0')) return NULL; @@ -3254,7 +3259,7 @@ 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"); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); @@ -3279,7 +3284,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"); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); @@ -3305,8 +3310,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) @@ -3329,7 +3335,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, errstr); } } XFREE (tmp_pathspec); @@ -3342,7 +3350,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 +3377,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 +3404,21 @@ 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); } void lt_setenv (const char *name, const char *value) { - LTWRAPPER_DEBUGPRINTF (("(lt_setenv) setting '%s' to '%s'\n", - (name ? name : "<NULL>"), - (value ? value : "<NULL>"))); + lt_debugprintf (__FILE__, __LINE__, + "(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 */ @@ -3442,9 +3466,10 @@ 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 : "<NULL>"), - (value ? value : "<NULL>"))); + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", + (name ? name : "<NULL>"), + (value ? value : "<NULL>")); if (name && *name && value && *value) { @@ -3463,9 +3488,10 @@ 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 : "<NULL>"), - (value ? value : "<NULL>"))); + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", + (name ? name : "<NULL>"), + (value ? value : "<NULL>")); if (name && *name && value && *value) { diff --git a/tests/cwrapper.at b/tests/cwrapper.at index 42f8d0f..66c9ce1 100644 --- a/tests/cwrapper.at +++ b/tests/cwrapper.at @@ -79,5 +79,57 @@ 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 -version-info=0.0.0 -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 "s/LTCFLAGS=.*/&' $debugwrapper_flags'/" < "$orig_LIBTOOL" | + sed "s/^lt_option_debug=/lt_option_debug=1/" > ./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 -version-info=0.0.0 -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