Hi Peter, others, * Ralf Wildenhues wrote on Wed, May 11, 2005 at 04:59:33PM CEST: > * Peter O'Gorman wrote on Wed, May 11, 2005 at 04:33:52PM CEST: > > Ralf Wildenhues wrote: > > > | My patches break one assumption held in libtool so far: that --dry-run > > | will cause no file changes. > > > > I understand your reasons for breaking this, but it freaks me out a little > > bit. > > Why?
How may I convince you? > > Have you reported the quadratic behavior to the bash maintainers? > > We need to file bugs with them about this too. > > No, but I will do so. It's not just bash, however, but virtually any > shell I could find. Done: http://lists.gnu.org/archive/html/bug-bash/2005-05/msg00611.html > > Note that some of your FIXMEs in the patches below are in my opinion > > not needed, if libtool got the argument list and -objectlist was not > > used then the kernel limit was not exceeded and $ECHO is fine. > > Oh yes, you are right. I started adding these mechanically to all > dependent variables instead of only the ones where the object list gets > expanded. Will post an updated patch. Here's a list of updated patches. Changes to previous proposed patches: - bugfix: in rename, we need to conserve the leading space in `$oldobjs'. - reword doubled status output about reloadable output. - output rename status output with func_echo for `libtool: link:' prefix. - Remove all irrelevant FIXMEs as pointed out by Peter. - New m4 macro OUTPUT_LONG_LIST: It may be used to output a list which may be longer than the command line limit. It is fast for the good cases (either builtin $ECHO and/or command line shorter than limit), and gets pretty slow for the worst case. I chose a macro as a cheap `inline' rather than a shell function for this because the shell function call uses a significant amount of time (in the fast case, obviously :). If the resulting about 1% size increase of `libtool' bugs anyone, we can change this. This macro is used to fix all the relevant FIXMEs added in the previous proposed patches. Right now, OUTPUT_LONG_LIST is defined right in ltmain.m4sh, which is probably against Libtool macro definition policies. Where should it go? If outside of ltmain.m4sh, it would probably need to be namespace-clean.. Outstanding issues: - As of now, each user of OUTPUT_LONG_LIST creates a separate scratch file within our scratch directory, for testing purposes. - What to do for MinGW which does not have all necessary tools? Keep the old renaming loop as a workaround in that case? - A good testsuite test will now really have to exceed the system command line length. - No error checking for write failures (full disk, etc.). I actually don't know whether it can be done portably in shell code without much hassle. Does anybody think this is worthwhile/necessary to pursue? - I don't know how to implement OUTPUT_LONG_LIST without a temp file. This is a question to think of for an eventual branch-2-0 backport of the fixme patch, in case you disapprove of temp files for it. The ranlib change will be in another patch and mail. OK to apply this to HEAD? Regards, Ralf
* m4/libtool.m4 (_LT_CHECK_POSIX_SORT, _LT_CHECK_READ_R): New macros to test sort(1) and read variations, define and use $posix_sort, $read_r. (_LT_SETUP): m4_require them. * config/ltmain.m4sh (func_generate_dlsyms): Use $posix_sort. --- m4/libtool.m4 2005-04-29 20:17:22.000000000 +0200 +++ m4/libtool.m4 2005-05-09 20:41:10.000000000 +0200 @@ -134,6 +134,8 @@ _LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl dnl m4_require([_LT_CHECK_XSI_SHELL])dnl +m4_require([_LT_CHECK_POSIX_SORT])dnl +m4_require([_LT_CHECK_READ_R])dnl m4_require([_LT_CMD_RELOAD])dnl m4_require([_LT_CHECK_MAGIC_METHOD])dnl m4_require([_LT_CMD_OLD_ARCHIVE])dnl @@ -6238,3 +6308,28 @@ _LT_EOF esac ]) + +# _LT_CHECK_POSIX_SORT +# -------------------- +# Whether sort(1) uses -kCOL or +COLM1, where COLM1 = COL - 1. +m4_defun([_LT_CHECK_POSIX_SORT], +[if sort -k3 </dev/null >/dev/null 2>&1; then + posix_sort=: +else + posix_sort=false +fi +_LT_DECL([], posix_sort, 1, [Whether sort(1) understands "-k"]) +])# _LT_CHECK_POSIX_SORT + +# _LT_CHECK_READ_R +# -------------------- +# Try to find out whether read understands "-r" +m4_defun([_LT_CHECK_READ_R], +[if echo bt | tr b '\\' | { read -r line; test "X$line" = 'X\t'; } 2>/dev/null +then + read_r='read -r' +else + read_r=read +fi +_LT_DECL([], read_r, 1, [read -r]) +])# _LT_CHECK_READ_R --- config/ltmain.m4sh 27 Apr 2005 20:30:38 -0000 1.66 +++ config/ltmain.m4sh 19 May 2005 20:18:50 -0000 @@ -850,11 +850,7 @@ # Try sorting and uniquifying the output. if $GREP -v "^: " < "$nlist" | - if sort -k 3 </dev/null >/dev/null 2>&1; then - sort -k 3 - else - sort +2 - fi | + if $posix_sort; then sort -k 3; else sort +2; fi | uniq > "$nlist"S; then : else
* config/ltmain.m4sh (OUTPUT_LONG_LIST): New macro to output lists which may exceed the command line length. (func_mode_link): Use OUTPUT_LONG_LIST. Index: config/ltmain.m4sh =================================================================== RCS file: /cvsroot/libtool/libtool/config/ltmain.m4sh,v retrieving revision 1.66 diff -u -r1.66 ltmain.m4sh --- config/ltmain.m4sh 27 Apr 2005 20:30:38 -0000 1.66 +++ config/ltmain.m4sh 19 May 2005 20:18:50 -0000 @@ -2143,6 +2139,30 @@ } +dnl OUTPUT_LONG_LIST(LIST, TEMPFILE, [SEDSCRIPT]) +dnl --------------------------------------------- +dnl Output LIST, which may be longer than the command line length, +dnl one item per line. LIST should be a whitespace-separates list. +dnl Leading, trailing, and multiple spaces will be removed. +dnl Optional post-processing may be done with SEDSCRIPT. +dnl This macro may need to use TEMPFILE as a temporary scratch space. +dnl The output is on STDOUT by default and may be redirected. +dnl May be used within backquotes, but not double-quoted backquotes. +dnl This macro is fast with a builtin $ECHO and/or a short list. +dnl +m4_define([OUTPUT_LONG_LIST], +[if $ECHO "X$1" >$2 2>/dev/null +then + $SP2NL <$2 | $Xsed -e '/^$/d' m4_if([$3],,, [-e $3]) +else +dnl You will appreciate the minutes spent in this loop.. + for tmp_elem in $1 + do + $ECHO "X$tmp_elem" + done | $SED -e 's/^X//' m4_if([$3],,, [-e $3]) +fi])dnl + + # func_mode_link arg... func_mode_link () { @@ -4484,7 +4538,8 @@ oldlibs="$oldlibs $output_objdir/$libname.$libext" # Transform .lo files to .o files. - oldobjs="$objs "`$ECHO "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP` + oldobjs="$objs "`OUTPUT_LONG_LIST([$libobjs], ["$always_gentop/scratch1"], + ["/\\.${libext}\$/d;$lo2o"]) | $NL2SP` fi # Eliminate all temporary directories. @@ -4977,7 +5032,10 @@ done # Use standard objects if they are pic - test -z "$pic_flag" && libobjs=`$ECHO "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + test -z "$pic_flag" && { + libobjs=`OUTPUT_LONG_LIST([$libobjs], ["$always_gentop/scratch2"], + ["$lo2o"]) | $NL2SP` + } # Prepare the list of exported symbols if test -z "$export_symbols"; then @@ -5346,8 +5397,10 @@ fi # Create the old-style object. - reload_objs="$objs$old_deplibs "`$ECHO "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test - + reload_objs="$objs$old_deplibs "`OUTPUT_LONG_LIST( + [$libobjs], + ["$always_gentop/scratch4"], + ["/\\.${libext}\$/d;/\\.lib\$/d;$lo2o"]) | $NL2SP`" $reload_conv_objs" output="$obj" cmds=$reload_cmds save_ifs="$IFS"; IFS='~'
* config/ltmain.m4sh (func_mode_link): Eliminate quadratic argument parsing with temp files, keep file descriptors (FD_LIBTOOL_ARGS, FD_COMPILE_COMMAND, FD_FINALIZE_COMMAND, FD_LIBOBJS, FD_NONPIC_OBJS): New. Use to avoid repeated reopening. Slurp in lists after parsing loop, make sure empty lists stay that way. (always_gentop): New variable to hold temp dir for scratch. Will be generated for every --mode=link invocation, also in dry run, and deleted upon exit. diff -ru config/ltmain.m4sh config/ltmain.m4sh --- config/ltmain.m4sh 27 Apr 2005 20:30:38 -0000 1.66 +++ config/ltmain.m4sh 19 May 2005 20:18:50 -0000 @@ -2166,10 +2186,32 @@ allow_undefined=yes ;; esac - libtool_args="$nonopt" + # Use files for long option lists, it avoids quadratic string handling. + # We need temp files, though, even in dry run + always_gentop=`opt_dry_run=false func_mktempdir` + trap "${RM}r \"$always_gentop\"" 0 +m4_define([FD_LIBTOOL_ARGS], [5])dnl +m4_define([FD_COMPILE_COMMAND], [6])dnl +m4_define([FD_FINALIZE_COMMAND], [7])dnl +m4_define([FD_LIBOBJS], [8])dnl +m4_define([FD_NONPIC_OBJS], [9])dnl + libtool_args_file=$always_gentop/libtool_args + compile_command_file=$always_gentop/compile_command + finalize_command_file=$always_gentop/finalize_command + libobjs_file=$always_gentop/libobjs + non_pic_objs_file=$always_gentop/non_pic_objs + exec FD_LIBTOOL_ARGS>"$libtool_args_file" \ + FD_COMPILE_COMMAND>"$compile_command_file" \ + FD_FINALIZE_COMMAND>"$finalize_command_file" \ + FD_LIBOBJS>"$libobjs_file" \ + FD_NONPIC_OBJS>"$non_pic_objs_file" + + $ECHO " " >&FD_LIBOBJS + $ECHO " " >&FD_NONPIC_OBJS + $ECHO " $nonopt" >&FD_LIBTOOL_ARGS + $ECHO " $nonopt" >&FD_COMPILE_COMMAND + $ECHO " $nonopt" >&FD_FINALIZE_COMMAND base_compile="$nonopt $@" - compile_command="$nonopt" - finalize_command="$nonopt" compile_rpath= finalize_rpath= @@ -2194,12 +2236,10 @@ export_symbols= export_symbols_regex= generated= - libobjs= ltlibs= module=no no_install=no objs= - non_pic_objects= precious_files_regex= prefer_static_libs=no preload=no @@ -2235,8 +2275,8 @@ if test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static # See comment for -static flag below, for more details. - compile_command="$compile_command $link_static_flag" - finalize_command="$finalize_command $link_static_flag" + $ECHO " $link_static_flag" >&FD_COMPILE_COMMAND + $ECHO " $link_static_flag" >&FD_FINALIZE_COMMAND fi else if test -z "$pic_flag" && test -n "$link_static_flag"; then @@ -2260,14 +2300,14 @@ shift func_quote_for_eval "$arg" qarg="$func_quote_for_eval_unquoted_result" - libtool_args="$libtool_args $func_quote_for_eval_result" + $ECHO " $func_quote_for_eval_result" >&FD_LIBTOOL_ARGS # If the previous option needs an argument, assign it. if test -n "$prev"; then case $prev in output) - compile_command="$compile_command @OUTPUT@" - finalize_command="$finalize_command @OUTPUT@" + $ECHO " @OUTPUT@" >&FD_COMPILE_COMMAND + $ECHO " @OUTPUT@" >&FD_FINALIZE_COMMAND ;; esac @@ -2275,8 +2315,8 @@ dlfiles|dlprefiles) if test "$preload" = no; then # Add the symbol object into the linking commands. - compile_command="$compile_command @SYMFILE@" - finalize_command="$finalize_command @SYMFILE@" + $ECHO " @SYMFILE@" >&FD_COMPILE_COMMAND + $ECHO " @SYMFILE@" >&FD_FINALIZE_COMMAND preload=yes fi case $arg in @@ -2398,7 +2438,7 @@ fi # A PIC object. - libobjs="$libobjs $pic_object" + $ECHO " $pic_object" >&FD_LIBOBJS arg="$pic_object" fi @@ -2408,7 +2448,7 @@ non_pic_object="$xdir$non_pic_object" # A standard non-PIC object - non_pic_objects="$non_pic_objects $non_pic_object" + $ECHO " $non_pic_object" >&FD_NONPIC_OBJS if test -z "$pic_object" || test "$pic_object" = none ; then arg="$non_pic_object" fi @@ -2416,7 +2456,7 @@ # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object="$pic_object" - non_pic_objects="$non_pic_objects $non_pic_object" + $ECHO " $non_pic_object" >&FD_NONPIC_OBJS fi else # Only an error if not doing a dry-run. @@ -2427,8 +2467,8 @@ pic_object=`$ECHO "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"` non_pic_object=`$ECHO "X${xdir}${arg}" | $Xsed -e "$lo2o"` - libobjs="$libobjs $pic_object" - non_pic_objects="$non_pic_objects $non_pic_object" + $ECHO " $pic_object" >&FD_LIBOBJS + $ECHO " $non_pic_object" >&FD_NONPIC_OBJS else func_fatal_error "\`$arg' is not a valid libtool object" fi @@ -2487,23 +2527,23 @@ linker_flags="$linker_flags $qarg" compiler_flags="$compiler_flags $qarg" prev= - compile_command="$compile_command $qarg" - finalize_command="$finalize_command $qarg" + $ECHO " $qarg" >&FD_COMPILE_COMMAND + $ECHO " $qarg" >&FD_FINALIZE_COMMAND continue ;; xcompiler) compiler_flags="$compiler_flags $qarg" prev= - compile_command="$compile_command $qarg" - finalize_command="$finalize_command $qarg" + $ECHO " $qarg" >&FD_COMPILE_COMMAND + $ECHO " $qarg" >&FD_FINALIZE_COMMAND continue ;; xlinker) linker_flags="$linker_flags $qarg" compiler_flags="$compiler_flags $wl$qarg" prev= - compile_command="$compile_command $wl$qarg" - finalize_command="$finalize_command $wl$qarg" + $ECHO " $wl$qarg" >&FD_COMPILE_COMMAND + $ECHO " $wl$qarg" >&FD_FINALIZE_COMMAND continue ;; *) @@ -2574,8 +2614,8 @@ -L[[A-Z]][[A-Z]]*:*) case $with_gcc/$host in no/*-*-irix* | /*-*-irix*) - compile_command="$compile_command $arg" - finalize_command="$finalize_command $arg" + $ECHO " $arg" >&FD_COMPILE_COMMAND + $ECHO " $arg" >&FD_FINALIZE_COMMAND ;; esac continue @@ -2657,17 +2697,17 @@ # Tru64 UNIX uses -model [arg] to determine the layout of C++ # classes, name mangling, and exception handling. -model) - compile_command="$compile_command $arg" compiler_flags="$compiler_flags $arg" - finalize_command="$finalize_command $arg" + $ECHO " $arg" >&FD_COMPILE_COMMAND + $ECHO " $arg" >&FD_FINALIZE_COMMAND prev=xcompiler continue ;; -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe) compiler_flags="$compiler_flags $arg" - compile_command="$compile_command $arg" - finalize_command="$finalize_command $arg" + $ECHO " $arg" >&FD_COMPILE_COMMAND + $ECHO " $arg" >&FD_FINALIZE_COMMAND case "$new_inherited_linker_flags " in *" $arg "*) ;; * ) new_inherited_linker_flags="$new_inherited_linker_flags $arg" ;; @@ -2840,8 +2880,8 @@ -64|-mips[[0-9]]|-r[[0-9]][[0-9]]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" - compile_command="$compile_command $arg" - finalize_command="$finalize_command $arg" + $ECHO " $arg" >&FD_COMPILE_COMMAND + $ECHO " $arg" >&FD_FINALIZE_COMMAND compiler_flags="$compiler_flags $arg" continue ;; @@ -2906,7 +2946,7 @@ fi # A PIC object. - libobjs="$libobjs $pic_object" + $ECHO " $pic_object" >&FD_LIBOBJS arg="$pic_object" fi @@ -2916,7 +2956,7 @@ non_pic_object="$xdir$non_pic_object" # A standard non-PIC object - non_pic_objects="$non_pic_objects $non_pic_object" + $ECHO " $non_pic_object" >&FD_NONPIC_OBJS if test -z "$pic_object" || test "$pic_object" = none ; then arg="$non_pic_object" fi @@ -2924,7 +2964,7 @@ # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object="$pic_object" - non_pic_objects="$non_pic_objects $non_pic_object" + $ECHO " $non_pic_object" >&FD_NONPIC_OBJS fi else # Only an error if not doing a dry-run. @@ -2935,8 +2975,8 @@ pic_object=`$ECHO "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"` non_pic_object=`$ECHO "X${xdir}${arg}" | $Xsed -e "$lo2o"` - libobjs="$libobjs $pic_object" - non_pic_objects="$non_pic_objects $non_pic_object" + $ECHO " $pic_object" >&FD_LIBOBJS + $ECHO " $non_pic_object" >&FD_NONPIC_OBJS else func_fatal_error "\`$arg' is not a valid libtool object" fi @@ -2978,11 +3018,25 @@ # Now actually substitute the argument into the commands. if test -n "$arg"; then - compile_command="$compile_command $arg" - finalize_command="$finalize_command $arg" + $ECHO " $arg" >&FD_COMPILE_COMMAND + $ECHO " $arg" >&FD_FINALIZE_COMMAND fi done # argument parsing loop + exec FD_LIBTOOL_ARGS>&- \ + FD_COMPILE_COMMAND>&- \ + FD_FINALIZE_COMMAND>&- \ + FD_LIBOBJS>&- \ + FD_NONPIC_OBJS>&- + libtool_args=`$SED 's/^ //' <"$libtool_args_file" | $NL2SP` + compile_command=`$SED 's/^ //' <"$compile_command_file" | $NL2SP` + finalize_command=`$SED 's/^ //' <"$finalize_command_file" | $NL2SP` + libobjs=`$SED 's/^ //' <"$libobjs_file" | $NL2SP` + non_pic_objects=`$SED 's/^ //' <"$non_pic_objs_file" | $NL2SP` + # Do not let `test -z' fail: + case $libobjs in ' ') libobjs=;; esac + case $non_pic_objects in ' ') non_pic_objects=;; esac + test -n "$prev" && \ func_fatal_help "the \`$prevarg' option requires an argument"
* config/ltmain.m4sh (func_mode_link): Drop `expr: command line too long' error. (func_mode_link) [ gnu, aix ]: Rewrite ld script creation to avoid repeated file opening. (func_mode_link): Rewrite partial linking to avoid quadratic scaling by use of temp files, fold, split, and OUTPUT_LONG_LIST. --- config/ltmain.m4sh 27 Apr 2005 20:30:38 -0000 1.66 +++ config/ltmain.m4sh 19 May 2005 20:18:50 -0000 @@ -5065,14 +5123,14 @@ fi fi - if test "X$skipped_export" != "X:" && len=`expr "X$test_cmds" : ".*"` && + if test "X$skipped_export" != "X:" && len=`expr "X$test_cmds" : ".*" 2>/dev/null` && test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then : else # The command line is too long to link in one step, link piecewise # or, if using GNU ld and skipped_export is not :, use a linker # script. - func_echo "creating reloadable object files..." + func_echo "command line too long for linking..." # Save the value of $output and $libobjs because we want to # use them later. If we have whole_archive_flag_spec, we @@ -5087,70 +5145,63 @@ fi save_output=$output output_la=`$ECHO "X$output" | $Xsed -e "$basename"` - - # Clear the reloadable object creation command queue and - # initialize k to one. - test_cmds= - concat_cmds= - objlist= delfiles= - last_robj= - k=1 if test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then output=${output_objdir}/${output_la}.lnkscript func_echo "creating GNU ld script: $output" - $ECHO 'INPUT (' > $output - for obj in $save_libobjs - do - $ECHO \""$obj"\" >> $output - done - $ECHO ')' >> $output + ( echo 'INPUT (' + OUTPUT_LONG_LIST([$save_libobjs], ["$always_gentop/scratch3"], ['s/^/"/;s/$/"/']) + echo ')' + ) >"$output" delfiles="$delfiles $output" elif test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then output=${output_objdir}/${output_la}.lnk func_echo "creating linker input file list: $output" - : > $output - for obj in $save_libobjs - do - $ECHO "$obj" >> $output - done + OUTPUT_LONG_LIST([$save_libobjs], ["$always_gentop/scratch3"]) >"$output" delfiles="$delfiles $output" - output=\"$file_list_spec$output\" + output="$file_list_spec$output" else func_echo "creating reloadable object files..." - output=$output_objdir/$output_la-${k}.$objext - # Loop over the list of objects to be linked. - for obj in $save_libobjs + # Clear the reloadable object creation command queue and + # initialize k to one. + concat_cmds= + objlist= + last_robj= + save_libobjs_file=$always_gentop/save_libobjs + save_libobjs_base=$always_gentop/save_libobjs_sep + + OUTPUT_LONG_LIST([$save_libobjs], + ["$always_gentop/scratch3"]) >"$save_libobjs_file" + eval test_cmds=\"$reload_cmds $objlist $last_robj\" + len_netto=`expr "X$test_cmds" : ".*"` \ + || func_fatal_error "too many arguments in \`reload_cmds'" + test "$len_netto" -lt "$max_cmd_len" \ + || func_fatal_error "too many arguments in \`reload_cmds'" + len_allowed=`expr "$max_cmd_len" - "$len_netto"` + func_show_eval "${RM} \"$save_libobjs_base\"?*" + # `fold' accepts long lines, `split' should too. + # We have to split, because `read' is limited to text files. + ( $NL2SP <"$save_libobjs_file"; echo ) \ + | fold -b -s -w "$len_allowed" \ + | split -l 1 - "$save_libobjs_base" + k=0 + kmax=`( set X "$save_libobjs_base"?*; shift; echo $#)` + for objfile in $save_libobjs_base?* do - eval test_cmds=\"$reload_cmds $objlist $last_robj\" - if test "X$objlist" = X || - { len=`expr "X$test_cmds" : ".*"` && - test "$len" -le "$max_cmd_len"; }; then - objlist="$objlist $obj" + k=`expr $k + 1` + output=$output_objdir/$output_la-${k}.$objext + objlist=' '`cat "$objfile"` + if test "$k" -eq 1 ; then + # The first file doesn't have a previous command to add. + eval concat_cmds=\"$reload_cmds $objlist $last_robj\" else - # The command $test_cmds is almost too long, add a - # command to the queue. - if test "$k" -eq 1 ; then - # The first file doesn't have a previous command to add. - eval concat_cmds=\"$reload_cmds $objlist $last_robj\" - else - # All subsequent reloadable object files will link in - # the last one created. - eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj\" - fi - last_robj=$output_objdir/$output_la-${k}.$objext - k=`expr $k + 1` - output=$output_objdir/$output_la-${k}.$objext - objlist=$obj - len=1 + # All subsequent reloadable object files will link in + # the last one created. + eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj\" fi + last_robj=$output done - # Handle the remaining objects by creating one last - # reloadable object file. All subsequent reloadable object - # files will link in the last one created. - test -z "$concat_cmds" || concat_cmds=$concat_cmds~ - eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\" if ${skipped_export-false}; then func_echo "generating symbol list for \`$libname.la'" @@ -5164,7 +5215,7 @@ # Set up a command to remove the reloadable object files # after they are used. i=0 - while test "$i" -lt "$k" + while test "$i" -lt "$kmax" do i=`expr $i + 1` delfiles="$delfiles $output_objdir/$output_la-${i}.$objext"
* config/ltmain.m4sh (func_mode_link): Rewrite duplicate object name renaming to avoid quadratic scaling by use of temp files, paste, join, OUTPUT_LONG_LIST. Breaks if file names contain newlines (and, if `read' does not support `-r', also backslashes). Hide `expr: argument list too long' error. diff -u -r1.66 ltmain.m4sh --- config/ltmain.m4sh 27 Apr 2005 20:30:38 -0000 1.66 +++ config/ltmain.m4sh 19 May 2005 20:18:50 -0000 @@ -6298,47 +6351,45 @@ # static archive out of a convenience library, or when linking # the entirety of a libtool archive into another (currently # not supported by libtool). - if (for obj in $oldobjs - do - func_basename "$obj" - $ECHO "$func_basename_result" - done | sort | sort -uc >/dev/null 2>&1); then - : - else + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + func_mkdir_p "$gentop" + objs_bnames=$always_gentop/objs_basenames + objs_nonuniq=$always_gentop/objs_nonuniq + replace_script=$always_gentop/replace_script + objs_file=$always_gentop/objs + OUTPUT_LONG_LIST([$oldobjs], ["$always_gentop/scratch6"], ["$basename"]) >"$objs_bnames" + sort "$objs_bnames" | uniq -d > "$objs_nonuniq" + if test -s "$objs_nonuniq" + then - $ECHO "copying selected object files to avoid basename conflicts..." - gentop="$output_objdir/${outputname}x" - generated="$generated $gentop" - func_mkdir_p "$gentop" - save_oldobjs=$oldobjs - oldobjs= - counter=1 - for obj in $save_oldobjs + func_echo "copying selected object files to avoid basename conflicts..." + : >"$replace_script" + # Make sure we use unique names: find highest number currently in use. + counter=`$SED -n ['/^lt-[0-9][0-9]*/ { s/^lt-//; s/[^0-9].*//; p; }'] "$objs_bnames" \ + | sort -n | $SED -n '$p'` + OUTPUT_LONG_LIST([$oldobjs], ["$always_gentop/scratch7"]) >"$objs_file" + # Create a list with: line number, object basename, object name. + # Sort it by basename, then pick out all lines corresponding to conflicts. + # The last sort merely cosmetic. + sed = "$objs_bnames" | + sed 'N;s/\n/ /' | + paste - "$objs_file" | + if $posix_sort; then sort -k2; else sort +1; fi | + join -1 2 - "$objs_nonuniq" | + if $posix_sort; then sort -k2n; else sort -n +1; fi | + while $read_r objbase line obj do - func_basename "$obj" - objbase="$func_basename_result" - case " $oldobjs " in - " ") oldobjs=$obj ;; - *[[\ /]]"$objbase "*) - while :; do - # Make sure we don't pick an alternate name that also - # overlaps. - newobj=lt$counter-$objbase - counter=`expr $counter + 1` - case " $oldobjs " in - *[[\ /]]"$newobj "*) ;; - *) if test ! -f "$gentop/$newobj"; then break; fi ;; - esac - done - func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" - oldobjs="$oldobjs $gentop/$newobj" - ;; - *) oldobjs="$oldobjs $obj" ;; - esac + counter=`expr $counter + 1` + newobj=lt$counter-$objbase + func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" + $ECHO "$line c\\ +$gentop/$newobj" >>"$replace_script" done + oldobjs=' '`$SED -f "$replace_script" "$objs_file" | $NL2SP` fi eval cmds=\"$old_archive_cmds\" - if len=`expr "X$cmds" : ".*"` && + if len=`expr "X$cmds" : ".*" 2>/dev/null` && test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then cmds=$old_archive_cmds else
* config/ltmain.m4sh (func_mode_link): Rewrite piecewise old archive linking to avoid quadratic loop. Makes use of fold, split, temp files, and OUTPUT_LONG_LIST. * tests/pdemo-conf.test: Adjust for the fact that we require $old_archive_cmds with empty list of objects to fit in the command line. diff -u -r1.66 ltmain.m4sh --- config/ltmain.m4sh 27 Apr 2005 20:30:38 -0000 1.66 +++ config/ltmain.m4sh 19 May 2005 20:18:50 -0000 @@ -6348,38 +6399,35 @@ RANLIB=: objlist= concat_cmds= - save_oldobjs=$oldobjs - # Is there a better way of finding the last object in the list? - for obj in $save_oldobjs - do - last_oldobj=$obj - done - for obj in $save_oldobjs + OUTPUT_LONG_LIST([$oldobjs], ["$always_gentop/scratch8"]) >"$objs_file" + oldobjs= + objs_split_base=$always_gentop/objs_split + eval test_cmds=\"$old_archive_cmds\" + len_netto=`expr "X$test_cmds" : ".*"` \ + || func_fatal_error "too many arguments in \`old_archive_cmds'" + test "$len_netto" -lt "$max_cmd_len" \ + || func_fatal_error "too many arguments in \`old_archive_cmds'" + len_allowed=`expr "$max_cmd_len" - "$len_netto"` + ${RM} "$objs_split_base"?* + # `fold' accepts long lines, `split' should too. + # We have to split, because `read' is limited to text files. + ( $NL2SP <"$objs_file"; echo ) \ + | fold -b -s -w "$len_allowed" \ + | split -l 1 - "$objs_split_base" + oldobjs= + for objfile in "$objs_split_base"?* last do - oldobjs="$objlist $obj" - objlist="$objlist $obj" - eval test_cmds=\"$old_archive_cmds\" - if len=`expr "X$test_cmds" : ".*"` && - test "$len" -le "$max_cmd_len"; then - : - else - # the above command should be used before it gets too long - oldobjs=$objlist - if test "$obj" = "$last_oldobj" ; then - RANLIB=$save_RANLIB - fi + case $objfile in last) RANLIB=$save_RANLIB;; esac + case $oldobjs in '') ;; + *) test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" - objlist= - fi + ;; + esac + case $objfile in last) ;; *) oldobjs=' '`cat "$objfile"`;; esac done - RANLIB=$save_RANLIB - oldobjs=$objlist - if test "X$oldobjs" = "X" ; then - eval cmds=\"\$concat_cmds\" - else - eval cmds=\"\$concat_cmds~\$old_archive_cmds\" - fi + + eval cmds=\"\$concat_cmds\" fi fi save_ifs="$IFS"; IFS='~' Index: tests/pdemo-conf.test =================================================================== RCS file: /cvsroot/libtool/libtool/tests/pdemo-conf.test,v retrieving revision 1.12 diff -u -r1.12 pdemo-conf.test --- tests/pdemo-conf.test 22 Apr 2005 10:10:30 -0000 1.12 +++ tests/pdemo-conf.test 6 May 2005 16:59:57 -0000 @@ -30,7 +30,7 @@ func_check_static_shared "yes" "yes" if test -f ./libtool ; then - sed 's/^max_cmd_len=*/max_cmd_len=24 # /g' ./libtool > ltnew + sed 's/^max_cmd_len=*/max_cmd_len=96 # /g' ./libtool > ltnew else exit 1 fi