* bootstrap (slurp): Work even in environments where "ls" defaults
[platform/upstream/coreutils.git] / bootstrap
1 #! /bin/sh
2
3 # Bootstrap this package from checked-out sources.
4
5 # Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
6
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3, or (at your option)
10 # any later version.
11
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 # GNU General Public License for more details.
16
17 # You should have received a copy of the GNU General Public License
18 # along with this program; if not, write to the Free Software
19 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 # 02110-1301, USA.
21
22 # Written by Paul Eggert.
23
24 nl='
25 '
26
27 # Ensure file names are sorted consistently across platforms.
28 # Also, ensure diagnostics are in English, e.g., "wget --help" below.
29 LC_ALL=C
30 export LC_ALL
31
32 local_gl_dir=gl
33
34 # Temporary directory names.
35 bt='._bootmp'
36 bt_regex=`echo "$bt"| sed 's/\./[.]/g'`
37 bt2=${bt}2
38
39 usage() {
40   echo >&2 "\
41 Usage: $0 [OPTION]...
42 Bootstrap this package from the checked-out sources.
43
44 Options:
45  --gnulib-srcdir=DIRNAME  Specify the local directory where gnulib
46                           sources reside.  Use this if you already
47                           have gnulib sources on your machine, and
48                           do not want to waste your bandwidth downloading
49                           them again.
50  --copy                   Copy files instead of creating symbolic links.
51  --force                  Attempt to bootstrap even if the sources seem
52                           not to have been checked out.
53  --skip-po                Do not download po files.
54  --cvs-user=USERNAME      Set the username to use when checking out
55                           sources from the gnulib repository.
56
57 If the file bootstrap.conf exists in the current working directory, its
58 contents are read as shell variables to configure the bootstrap.
59
60 Running without arguments will suffice in most cases.
61 "
62 }
63
64 # Configuration.
65
66 # Name of the Makefile.am
67 gnulib_mk=gnulib.mk
68
69 # List of gnulib modules needed.
70 gnulib_modules=
71
72 # Any gnulib files needed that are not in modules.
73 gnulib_files=
74
75 # Translation Project URL, for the registry of all projects
76 # and for the translation-team master directory.
77 TP_URL="http://translationproject.org/latest/"
78
79 extract_package_name='
80   /^AC_INIT(/{
81      /.*,.*,.*,/{
82        s///
83        s/[][]//g
84        p
85        q
86      }
87      s/AC_INIT(\[*//
88      s/]*,.*//
89      s/^GNU //
90      y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
91      s/[^A-Za-z0-9_]/-/g
92      p
93   }
94 '
95 package=`sed -n "$extract_package_name" configure.ac` || exit
96 gnulib_name=lib$package
97
98 build_aux=build-aux
99 # Extra files from gnulib, which override files from other sources.
100 gnulib_extra_files="
101         $build_aux/install-sh
102         $build_aux/missing
103         $build_aux/mdate-sh
104         $build_aux/texinfo.tex
105         $build_aux/depcomp
106         $build_aux/config.guess
107         $build_aux/config.sub
108         doc/INSTALL
109 "
110
111 # Additional gnulib-tool options to use.  Use "\newline" to break lines.
112 gnulib_tool_option_extras=
113
114 # Other locale categories that need message catalogs.
115 EXTRA_LOCALE_CATEGORIES=
116
117 # Additional xgettext options to use.  Use "\\\newline" to break lines.
118 XGETTEXT_OPTIONS='\\\
119  --flag=_:1:pass-c-format\\\
120  --flag=N_:1:pass-c-format\\\
121  --flag=error:3:c-format --flag=error_at_line:5:c-format\\\
122 '
123
124 # Files we don't want to import.
125 excluded_files=
126
127 # File that should exist in the top directory of a checked out hierarchy,
128 # but not in a distribution tarball.
129 checkout_only_file=README-hacking
130
131 # Whether to use copies instead of symlinks.
132 copy=false
133
134 # Override the default configuration, if necessary.
135 test -r bootstrap.conf && . ./bootstrap.conf
136
137 # Translate configuration into internal form.
138
139 # Parse options.
140
141 for option
142 do
143   case $option in
144   --help)
145     usage
146     exit;;
147   --gnulib-srcdir=*)
148     GNULIB_SRCDIR=`expr "$option" : '--gnulib-srcdir=\(.*\)'`;;
149   --cvs-user=*)
150     CVS_USER=`expr "$option" : '--cvs-user=\(.*\)'`;;
151   --skip-po)
152     SKIP_PO=t;;
153   --force)
154     checkout_only_file=;;
155   --copy)
156     copy=true;;
157   *)
158     echo >&2 "$0: $option: unknown option"
159     exit 1;;
160   esac
161 done
162
163 if test -n "$checkout_only_file" && test ! -r "$checkout_only_file"; then
164   echo "$0: Bootstrapping from a non-checked-out distribution is risky." >&2
165   exit 1
166 fi
167
168 # If $STR is not already on a line by itself in $FILE, insert it,
169 # sorting the new contents of the file and replacing $FILE with the result.
170 insert_sorted_if_absent() {
171   file=$1
172   str=$2
173   echo "$str" | sort -u - $file | cmp -s - $file \
174     || echo "$str" | sort -u - $file -o $file \
175     || exit 1
176 }
177
178 # Die if there is no AC_CONFIG_AUX_DIR($build_aux) line in configure.ac.
179 found_aux_dir=no
180 grep '^[         ]*AC_CONFIG_AUX_DIR(\['"$build_aux"'\])' configure.ac \
181     >/dev/null && found_aux_dir=yes
182 grep '^[         ]*AC_CONFIG_AUX_DIR('"$build_aux"')' configure.ac \
183     >/dev/null && found_aux_dir=yes
184 if test $found_aux_dir = no; then
185   echo "$0: expected line not found in configure.ac. Add the following:" >&2
186   echo "  AC_CONFIG_AUX_DIR([$build_aux])" >&2
187   exit 1
188 fi
189
190 # If $build_aux doesn't exist, create it now, otherwise some bits
191 # below will malfunction.  If creating it, also mark it as ignored.
192 if test ! -d $build_aux; then
193   mkdir $build_aux
194   for ig in .cvsignore .gitignore; do
195     test -f $ig && insert_sorted_if_absent $ig $build_aux
196   done
197 fi
198
199 echo "$0: Bootstrapping from checked-out $package sources..."
200
201 cleanup_gnulib() {
202   status=$?
203   rm -fr gnulib
204   exit $status
205 }
206
207 # Get gnulib files.
208
209 case ${GNULIB_SRCDIR--} in
210 -)
211   if [ ! -d gnulib ]; then
212     echo "$0: getting gnulib files..."
213
214     case ${CVS_AUTH-pserver} in
215     pserver)
216       CVS_PREFIX=':pserver:anonymous@';;
217     ssh)
218       CVS_PREFIX="$CVS_USER${CVS_USER+@}";;
219     *)
220       echo "$0: $CVS_AUTH: Unknown CVS access method" >&2
221       exit 1;;
222     esac
223
224     case $CVS_RSH in
225     '') CVS_RSH=ssh; export CVS_RSH;;
226     esac
227
228     trap cleanup_gnulib 1 2 13 15
229
230     cvs -z3 -q -d ${CVS_PREFIX}cvs.savannah.gnu.org:/cvsroot/gnulib co gnulib ||
231       cleanup_gnulib
232
233     trap - 1 2 13 15
234   fi
235   GNULIB_SRCDIR=gnulib
236 esac
237
238 gnulib_tool=$GNULIB_SRCDIR/gnulib-tool
239 <$gnulib_tool || exit
240
241 # Get translations.
242
243 get_translations() {
244   subdir=$1
245   domain=$2
246
247   case $WGET_COMMAND in
248   '')
249     echo "$0: wget not available; skipping translations";;
250   ?*)
251     echo "$0: getting translations into $subdir for $domain..." &&
252
253     (cd $subdir && rm -f dummy `ls | sed -n '/\.gmo$/p; /\.po/p'` &&
254      $WGET_COMMAND -r -l1 -nd -np -A.po $TP_URL/$domain)
255     ;;
256   esac &&
257   ls "$subdir"/*.po 2>/dev/null |
258     sed 's|.*/||; s|\.po$||' >"$subdir/LINGUAS"
259 }
260
261 case $SKIP_PO in
262 '')
263   case `wget --help` in
264   *'--no-cache'*)
265     WGET_COMMAND='wget -nv --no-cache';;
266   *'--cache=on/off'*)
267     WGET_COMMAND='wget -nv --cache=off';;
268   *'--non-verbose'*)
269     WGET_COMMAND='wget -nv';;
270   *)
271     WGET_COMMAND='';;
272   esac
273
274   if test -d po; then
275     get_translations po $package || exit
276   fi
277
278   if test -d runtime-po; then
279     get_translations runtime-po $package-runtime || exit
280   fi;;
281 esac
282
283 symlink_to_dir()
284 {
285   src=$1/$2
286   dst=${3-$2}
287
288   test -f "$src" && {
289
290     # If the destination directory doesn't exist, create it.
291     # This is required at least for "lib/uniwidth/cjk.h".
292     dst_dir=`dirname "$dst"`
293     test -d "$dst_dir" || mkdir -p "$dst_dir"
294
295     if $copy; then
296       {
297         test ! -h "$dst" || {
298           echo "$0: rm -f $dst" &&
299           rm -f "$dst"
300         }
301       } &&
302       test -f "$dst" &&
303       cmp -s "$src" "$dst" || {
304         echo "$0: cp -fp $src $dst" &&
305         cp -fp "$src" "$dst"
306       }
307     else
308       test -h "$dst" &&
309       src_ls=`ls -diL "$src" 2>/dev/null` && set $src_ls && src_i=$1 &&
310       dst_ls=`ls -diL "$dst" 2>/dev/null` && set $dst_ls && dst_i=$1 &&
311       test "$src_i" = "$dst_i" || {
312         dot_dots=
313         case $src in
314         /*) ;;
315         *)
316           case /$dst/ in
317           *//* | */../* | */./* | /*/*/*/*/*/)
318              echo >&2 "$0: invalid symlink calculation: $src -> $dst"
319              exit 1;;
320           /*/*/*/*/)    dot_dots=../../../;;
321           /*/*/*/)      dot_dots=../../;;
322           /*/*/)        dot_dots=../;;
323           esac;;
324         esac
325
326         echo "$0: ln -fs $dot_dots$src $dst" &&
327         ln -fs "$dot_dots$src" "$dst"
328       }
329     fi
330   }
331 }
332
333 cp_mark_as_generated()
334 {
335   cp_src=$1
336   cp_dst=$2
337
338   if cmp -s "$cp_src" "$GNULIB_SRCDIR/$cp_dst"; then
339     symlink_to_dir "$GNULIB_SRCDIR" "$cp_dst"
340   elif cmp -s "$cp_src" "$local_gl_dir/$cp_dst"; then
341     symlink_to_dir $local_gl_dir "$cp_dst"
342   else
343     case $cp_dst in
344       *.[ch])             c1='/* '; c2=' */';;
345       *.texi)             c1='@c '; c2=     ;;
346       *.m4|*/Make*|Make*) c1='# ' ; c2=     ;;
347       *)                  c1=     ; c2=     ;;
348     esac
349
350     if test -z "$c1"; then
351       cmp -s "$cp_src" "$cp_dst" || {
352         echo "$0: cp -f $cp_src $cp_dst" &&
353         rm -f "$cp_dst" &&
354         sed "s!$bt_regex/!!g" "$cp_src" > "$cp_dst"
355       }
356     else
357       # Copy the file first to get proper permissions if it
358       # doesn't already exist.  Then overwrite the copy.
359       cp "$cp_src" "$cp_dst-t" &&
360       (
361         echo "$c1-*- buffer-read-only: t -*- vi: set ro:$c2" &&
362         echo "${c1}DO NOT EDIT! GENERATED AUTOMATICALLY!$c2" &&
363         sed "s!$bt_regex/!!g" "$cp_src"
364       ) > $cp_dst-t &&
365       if cmp -s "$cp_dst-t" "$cp_dst"; then
366         rm -f "$cp_dst-t"
367       else
368         echo "$0: cp $cp_src $cp_dst # with edits" &&
369         mv -f "$cp_dst-t" "$cp_dst"
370       fi
371     fi
372   fi
373 }
374
375 version_controlled_file() {
376   dir=$1
377   file=$2
378   found=no
379   if test -d CVS; then
380     grep -F "/$file/" $dir/CVS/Entries 2>/dev/null |
381              grep '^/[^/]*/[0-9]' > /dev/null && found=yes
382   elif test -d .git; then
383     git-rm -n "$dir/$file" > /dev/null 2>&1 && found=yes
384   else
385     echo "$0: no version control for $dir/$file?" >&2
386   fi
387   test $found = yes
388 }
389
390 slurp() {
391   for dir in . `(cd $1 && find * -type d -print)`; do
392     copied=
393     sep=
394     for file in `ls -a $1/$dir`; do
395       case $file in
396       .|..) continue;;
397       .*) continue;; # FIXME: should all file names starting with "." be ignored?
398       esac
399       test -d $1/$dir/$file && continue
400       for excluded_file in $excluded_files; do
401         test "$dir/$file" = "$excluded_file" && continue 2
402       done
403       if test $file = Makefile.am; then
404         copied=$copied${sep}$gnulib_mk; sep=$nl
405         remove_intl='/^[^#].*\/intl/s/^/#/;'"s!$bt_regex/!!g"
406         sed "$remove_intl" $1/$dir/$file | cmp -s - $dir/$gnulib_mk || {
407           echo "$0: Copying $1/$dir/$file to $dir/$gnulib_mk ..." &&
408           rm -f $dir/$gnulib_mk &&
409           sed "$remove_intl" $1/$dir/$file >$dir/$gnulib_mk
410         }
411       elif { test "${2+set}" = set && test -r $2/$dir/$file; } ||
412            version_controlled_file $dir $file; then
413         echo "$0: $dir/$file overrides $1/$dir/$file"
414       else
415         copied=$copied$sep$file; sep=$nl
416         if test $file = gettext.m4; then
417           echo "$0: patching m4/gettext.m4 to remove need for intl/* ..."
418           rm -f $dir/$file
419           sed '
420             /^AC_DEFUN(\[AM_INTL_SUBDIR],/,/^]/c\
421               AC_DEFUN([AM_INTL_SUBDIR], [
422             /^AC_DEFUN(\[gt_INTL_SUBDIR_CORE],/,/^]/c\
423               AC_DEFUN([gt_INTL_SUBDIR_CORE], [])
424             $a\
425               AC_DEFUN([gl_LOCK_EARLY], [])
426           ' $1/$dir/$file >$dir/$file
427         else
428           cp_mark_as_generated $1/$dir/$file $dir/$file
429         fi
430       fi || exit
431     done
432
433     for dot_ig in .cvsignore .gitignore; do
434       ig=$dir/$dot_ig
435       if test -n "$copied" && test -f $ig; then
436         insert_sorted_if_absent $ig "$copied"
437         # If an ignored file name ends with _.h, then also add
438         # the name with just ".h".  Many gnulib headers are generated,
439         # e.g., stdint_.h -> stdint.h, dirent_.h ->..., etc.
440         f=`echo "$copied"|sed 's/_\.h$/.h/'`
441         insert_sorted_if_absent $ig "$f"
442       fi
443     done
444   done
445 }
446
447
448 # Create boot temporary directories to import from gnulib and gettext.
449 rm -fr $bt $bt2 &&
450 mkdir $bt $bt2 || exit
451
452 # Import from gnulib.
453
454 gnulib_tool_options="\
455  --import\
456  --no-changelog\
457  --aux-dir $bt/$build_aux\
458  --doc-base $bt/doc\
459  --lib $gnulib_name\
460  --m4-base $bt/m4/\
461  --source-base $bt/lib/\
462  --tests-base $bt/tests\
463  --local-dir $local_gl_dir\
464 $gnulib_tool_option_extras\
465 "
466 echo "$0: $gnulib_tool $gnulib_tool_options --import ..."
467 $gnulib_tool $gnulib_tool_options --import $gnulib_modules &&
468 slurp $bt || exit
469
470 for file in $gnulib_files; do
471   symlink_to_dir "$GNULIB_SRCDIR" $file || exit
472 done
473
474
475 # Import from gettext.
476 with_gettext=yes
477 grep '^[         ]*AM_GNU_GETTEXT_VERSION(' configure.ac >/dev/null || \
478     with_gettext=no
479
480 if test $with_gettext = yes; then
481   echo "$0: (cd $bt2; autopoint) ..."
482   cp configure.ac $bt2 &&
483   (cd $bt2 && autopoint && rm configure.ac) &&
484   slurp $bt2 $bt || exit
485
486   rm -fr $bt $bt2 || exit
487 fi
488
489 # Coreutils is unusual in that it generates some of its test-related
490 # Makefile.am files.  That must be done before invoking automake.
491 mam_template=tests/Makefile.am.in
492 if test -f $mam_template; then
493   PERL=perl
494   for tool in cut head join pr sort tac tail test tr uniq wc; do
495     m=tests/$tool/Makefile.am
496     t=${m}t
497     rm -f $m $t
498     sed -n '1,/^##test-files-begin/p' $mam_template > $t
499     echo "x = $tool" >> $t
500     srcdir=tests/$tool
501     $PERL -I$srcdir -w -- tests/mk-script $srcdir --list >> $t
502     sed -n '/^##test-files-end/,$p' $mam_template >> $t
503     chmod -w $t
504     mv $t $m
505   done
506 fi
507
508 # Reconfigure, getting other files.
509
510 for command in \
511   libtool \
512   'aclocal --force -I m4' \
513   'autoconf --force' \
514   'autoheader --force' \
515   'automake --add-missing --copy --force-missing';
516 do
517   if test "$command" = libtool; then
518     grep '^[     ]*AM_PROG_LIBTOOL\>' configure.ac >/dev/null ||
519       continue
520     command='libtoolize -c -f'
521   fi
522   echo "$0: $command ..."
523   $command || exit
524 done
525
526
527 # Get some extra files from gnulib, overriding existing files.
528 for file in $gnulib_extra_files; do
529   case $file in
530   */INSTALL) dst=INSTALL;;
531   build-aux/*) dst=$build_aux/`expr "$file" : 'build-aux/\(.*\)'`;;
532   *) dst=$file;;
533   esac
534   symlink_to_dir "$GNULIB_SRCDIR" $file $dst || exit
535 done
536
537 if test $with_gettext = yes; then
538   # Create gettext configuration.
539   echo "$0: Creating po/Makevars from po/Makevars.template ..."
540   rm -f po/Makevars
541   sed '
542     /^EXTRA_LOCALE_CATEGORIES *=/s/=.*/= '"$EXTRA_LOCALE_CATEGORIES"'/
543     /^MSGID_BUGS_ADDRESS *=/s/=.*/= bug-'"$package"'@gnu.org/
544     /^XGETTEXT_OPTIONS *=/{
545       s/$/ \\/
546       a\
547           '"$XGETTEXT_OPTIONS"' $${end_of_xgettext_options+}
548     }
549   ' po/Makevars.template >po/Makevars
550
551   if test -d runtime-po; then
552     # Similarly for runtime-po/Makevars, but not quite the same.
553     rm -f runtime-po/Makevars
554     sed '
555       /^DOMAIN *=.*/s/=.*/= '"$package"'-runtime/
556       /^subdir *=.*/s/=.*/= runtime-po/
557       /^MSGID_BUGS_ADDRESS *=/s/=.*/= bug-'"$package"'@gnu.org/
558       /^XGETTEXT_OPTIONS *=/{
559         s/$/ \\/
560         a\
561             '"$XGETTEXT_OPTIONS_RUNTIME"' $${end_of_xgettext_options+}
562       }
563     ' <po/Makevars.template >runtime-po/Makevars
564
565     # Copy identical files from po to runtime-po.
566     (cd po && cp -p Makefile.in.in *-quot *.header *.sed *.sin ../runtime-po)
567   fi
568 fi
569
570 echo "$0: done.  Now you can run './configure'."