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